/**
 *	@file    algorithmTest.c
 *	@version 8e6f0e1 (HEAD -> master)
 *
 *	Crypto harness to check algorithms against known inputs/outputs.
 */
/*
 *	Copyright (c) 2013-2016 INSIDE Secure Corporation
 *	Copyright (c) PeerSec Networks, 2002-2011
 *	All Rights Reserved
 *
 *	The latest version of this code is available at http://www.matrixssl.org
 *
 *	This software is open source; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	This General Public License does NOT permit incorporating this software
 *	into proprietary programs.  If you are unable to comply with the GPL, a
 *	commercial license for this software may be purchased from INSIDE at
 *	http://www.insidesecure.com/
 *
 *	This program is distributed in WITHOUT ANY WARRANTY; without even the
 *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *	See the GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *	http://www.gnu.org/copyleft/gpl.html
 */
/******************************************************************************/

#include "crypto/cryptoApi.h"
#include "hmac_test_vectors.h"

#ifndef USE_SERVER_SIDE_SSL
#define USE_SERVER_SIDE_SSL
#endif

/******************************************************************************/
static int32 psPrngTests(void)
{
	int32 res;
	static unsigned char ch[70000];
	_psTrace("	PRNG small random generation... ");

	memset(ch, 0, sizeof(ch));
	res = matrixCryptoGetPrngData(ch, 3, NULL);
	if (res != 3 ||
		ch[0] + ch[1] + ch[2] < 6 || /* Probabilistic test */
		ch[4] != 0 ||
		ch[5] != 0)
	{
		_psTrace("FAILED\n");
		res = PS_FAILURE;
	} else {
		_psTrace("PASSED\n");
	}

	if (res != PS_FAILURE) {
		int i, sum;

		_psTrace("	PRNG large random generation... ");

		memset(ch, 0, sizeof(ch));
		sum = 0;
		res = matrixCryptoGetPrngData(ch + 1, 65532, NULL);
		res += matrixCryptoGetPrngData(ch + 1 + 65532, (69998-65532), NULL);
		for(i = 0; i < 70000; i++)
			sum += ch[i];
		if (res != 69998 ||
			sum < 5 * 70000 ||  /* Probabilistic test */
			sum > 250 * 70000 ||  /* Probabilistic test */
			ch[0] != 0 ||
			ch[69999] != 0)
		{
			_psTrace("FAILED\n");
			res = PS_FAILURE;
		} else {
			_psTrace("PASSED\n");
		}
	}

	return res < 0 ? res : PS_SUCCESS;
}

/******************************************************************************/
#ifdef USE_AES
#define AES_ITER	1000	/* For AES Block mode test */
static int32 psAesTestBlock(void)
{
	int32 err, i, y;
	psAesKey_t ekey, dkey;
	unsigned char tmp[2][16];

	static const struct {
		int32 keylen;
		unsigned char key[32], pt[16], ct[16];
	} tests[] = {
	{ 16,
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
		{ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
			0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
		}, {
		24,
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
		{ 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
			0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
		}, {
		32,
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
		{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
		{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
			0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
		}
	};

	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTraceInt("	AES-%d known vector test... ", tests[i].keylen * 8);
		if ((err = psAesInitBlockKey(&ekey, tests[i].key, tests[i].keylen, PS_AES_ENCRYPT))
				!= PS_SUCCESS) {
			_psTraceInt("FAILED:  psAesInitBlockKey returned %d\n", err);
			return err;
		}
		if ((err = psAesInitBlockKey(&dkey, tests[i].key, tests[i].keylen, PS_AES_DECRYPT))
				!= PS_SUCCESS) {
			_psTraceInt("FAILED:  psAesInitBlockKey returned %d\n", err);
			psAesClearBlockKey(&ekey);
			return err;
		}
		psAesEncryptBlock(&ekey, tests[i].pt, tmp[0]);
		psAesDecryptBlock(&dkey, tmp[0], tmp[1]);
		if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16))
		{
			_psTraceInt("FAILED: mem compare failed\n", i);
			if (memcmp(tmp[0], tests[i].ct, 16)) {
				psTraceCrypto("CT: ");
				for (i = 0; i < 16; i++) {
					_psTraceInt("%02x ", tmp[0][i]);
				}
				_psTrace("\n");
			} else {
				_psTrace("PT: ");
				for (i = 0; i < 16; i++) {
					_psTraceInt("%02x ", tmp[1][i]);
				}
				_psTrace("\n");
			}
			psAesClearBlockKey(&ekey);
			psAesClearBlockKey(&dkey);
			return -1;
		}
		_psTrace("PASSED\n");
/*
		Now see if we can encrypt all zero bytes 1000 times,
		decrypt and come back where we started
*/
		_psTraceInt("	AES-%d wind/unwind test... ", tests[i].keylen * 8);
		for (y = 0; y < 16; y++) tmp[0][y] = 0;
		for (y = 0; y < AES_ITER; y++) psAesEncryptBlock(&ekey, tmp[0], tmp[0]);
		for (y = 0; y < AES_ITER; y++) psAesDecryptBlock(&dkey, tmp[0], tmp[0]);
		for (y = 0; y < 16; y++) {
			if (tmp[0][y] != 0) {
				_psTraceInt("FAILED:  unable to unwind %d to zero\n", y);
				psAesClearBlockKey(&ekey);
				psAesClearBlockKey(&dkey);
				return -1;
			}
		}
		psAesClearBlockKey(&ekey);
		psAesClearBlockKey(&dkey);
		_psTrace("PASSED\n");
	}
	return 0;
}

/*
	Known vector test - AES-CBC
*/
static int32 psAesTestCBC(void)
{
	int32	err, i;
	psAesCbc_t	eCtx, dCtx;
	unsigned char tmp[2][16];

	static struct {
		int32 keylen;
		unsigned char key[32], iv[16], pt[16], ct[16];
	} tests[] = {
		{ 16,
		{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7,
			0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
			0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
		{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d,
			0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
		{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9,
			0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d }
		}, {
		24,
		{ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10,
			0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2,
			0x52, 0x2c, 0x6b, 0x7b },
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
			0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
		{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d,
			0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
		{ 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78,
			0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8 }
		}, {
		32,
		{ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae,
			0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61,
			0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
			0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },
		{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d,
			0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
		{ 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e,
			0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6 }
		}
	};


	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTraceInt("	AES-CBC-%d known vector test... ", tests[i].keylen * 8);
		if ((err = psAesInitCBC(&eCtx, tests[i].iv, tests[i].key, tests[i].keylen,
				PS_AES_ENCRYPT)) != PS_SUCCESS) {
			_psTraceInt("FAILED:  psAesInitCBC returned %d\n", err);
			return err;
		}
		if ((err = psAesInitCBC(&dCtx, tests[i].iv, tests[i].key, tests[i].keylen,
				PS_AES_DECRYPT)) != PS_SUCCESS) {
			_psTraceInt("FAILED:  psAesInitCBC returned %d\n", err);
			psAesClearCBC(&eCtx);
			return err;
		}
		psAesEncryptCBC(&eCtx, tests[i].pt, tmp[0], 16);
		psAesDecryptCBC(&dCtx, tmp[0], tmp[1], 16);
		if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16))
		{
			_psTraceInt("FAILED: mem compare failed\n", i);
			if (memcmp(tmp[0], tests[i].ct, 16)) {
				psTraceCrypto("CT: ");
				for (i = 0; i < 16; i++) {
					_psTraceInt("%02x ", tmp[0][i]);
				}
				_psTrace("\n");
			} else {
				_psTrace("PT: ");
				for (i = 0; i < 16; i++) {
					_psTraceInt("%02x ", tmp[1][i]);
				}
				_psTrace("\n");
			}
			psAesClearCBC(&eCtx);
			psAesClearCBC(&dCtx);
			return -1;
		}
		psAesClearCBC(&eCtx);
		psAesClearCBC(&dCtx);
		_psTrace("PASSED\n");
	}
	return 0;
}

#ifdef USE_AES_GCM
int32 psAesTestGCM(void)
{
	int32               res = PS_SUCCESS;
	int32				i, l;
	psAesGcm_t	eCtx;
	psAesGcm_t	dCtx;
	unsigned char		plaintext[4128];
	unsigned char		ciphertext[4128];
#ifndef USE_ONLY_DECRYPT_GCM_WITH_TAG
	unsigned char		tag[16];
#endif
	unsigned char       ciphertext_with_tag[4144];
	static unsigned char taglen[3] = { 8, 12, 16 };
	static char *tagmsg[] = {
		"	AES-GCM-%d known vector decrypt (taglen=8) test... ",
		"	AES-GCM-%d known vector decrypt (taglen=12) test... ",
		"	AES-GCM-%d known vector decrypt (taglen=16) test... ",
	};
	static char *tagmsg2[] = {
		"	AES-GCM-%d known vector decrypt (taglen=8 invalid) test... ",
		"	AES-GCM-%d known vector decrypt (taglen=12 invalid) test... ",
		"	AES-GCM-%d known vector decrypt (taglen=16 invalid) test... ",
	};

	static struct {
		int32 keylen, ptlen, aadlen;
		unsigned char key[32], iv[12], pt[4128], aad[32], ct[4128], tag[16];
	} tests[] = {
#ifndef USE_LIBSODIUM_AES_GCM
	{ 16, 16, 16,
		{	0xc9, 0x39, 0xcc, 0x13, 0x39, 0x7c, 0x1d, 0x37,
			0xde, 0x6a, 0xe0, 0xe1, 0xcb, 0x7c, 0x42, 0x3c },
		{	0xb3, 0xd8, 0xcc, 0x01, 0x7c, 0xbb, 0x89, 0xb3,
			0x9e, 0x0f, 0x67, 0xe2 },
		{	0xc3, 0xb3, 0xc4, 0x1f, 0x11, 0x3a, 0x31, 0xb7,
			0x3d, 0x9a, 0x5c, 0xd4, 0x32, 0x10, 0x30, 0x69},
		{	0x24, 0x82, 0x56, 0x02, 0xbd, 0x12, 0xa9, 0x84,
			0xe0, 0x09, 0x2d, 0x3e, 0x44, 0x8e, 0xda, 0x5f},
		{	0x93, 0xfe, 0x7d, 0x9e, 0x9b, 0xfd, 0x10, 0x34,
			0x8a, 0x56, 0x06, 0xe5, 0xca, 0xfa, 0x73, 0x54},
		{	0x00, 0x32, 0xa1, 0xdc, 0x85, 0xf1, 0xc9, 0x78,
			0x69, 0x25, 0xa2, 0xe7, 0x1d, 0x82, 0x72, 0xdd}
		},
	{ 16, 4128, 16,
		{	0xc9, 0x39, 0xcc, 0x13, 0x39, 0x7c, 0x1d, 0x37,
			0xde, 0x6a, 0xe0, 0xe1, 0xcb, 0x7c, 0x42, 0x3c },
		{	0xb3, 0xd8, 0xcc, 0x01, 0x7c, 0xbb, 0x89, 0xb3,
			0x9e, 0x0f, 0x67, 0xe2 },
	    {	0x00, },
		{	0x24, 0x82, 0x56, 0x02, 0xbd, 0x12, 0xa9, 0x84,
			0xe0, 0x09, 0x2d, 0x3e, 0x44, 0x8e, 0xda, 0x5f},
		{	0x50, 0x4d, 0xb9, 0x81, 0x8a, 0xc7, 0x21, 0x83, 0xb7, 0xcc,
			0x5a, 0x31, 0xf8, 0xea, 0x43, 0x3d, 0x46, 0xb1, 0x85, 0x3f,
			0x8b, 0x9b, 0x8d, 0xd3, 0xfe, 0x06, 0x84, 0x42, 0xd9, 0x08,
			0x98, 0x43, 0xe7, 0xbd, 0x0b, 0x32, 0x02, 0x10, 0x39, 0xae,
			0x3b, 0xcb, 0x39, 0x5d, 0x76, 0x47, 0xd8, 0xc9, 0xac, 0xa1,
			0x72, 0xe7, 0x54, 0x98, 0xcf, 0x5f, 0x91, 0x56, 0x90, 0x51,
			0x79, 0x3a, 0xf3, 0x38, 0x4e, 0xb2, 0x8d, 0x1a, 0x27, 0x3c,
			0xa9, 0xdb, 0x8f, 0xcd, 0x48, 0x14, 0x97, 0xba, 0xd7, 0x4b,
			0x7c, 0x64, 0xc4, 0x78, 0xf7, 0x8f, 0x81, 0x22, 0x71, 0xa6,
			0x90, 0xf4, 0x30, 0x47, 0xd8, 0x7f, 0x96, 0xd9, 0x6c, 0x21,
			0xc0, 0x47, 0xfd, 0xc8, 0x45, 0xf8, 0x7d, 0xdf, 0x8c, 0x2b,
			0x1a, 0xe5, 0x73, 0x29, 0x7f, 0x26, 0x55, 0xb4, 0x11, 0x4a,
			0x08, 0x2d, 0x30, 0xab, 0x12, 0x58, 0x96, 0xf8, 0xfa, 0x99,
			0x75, 0x6a, 0x0c, 0x94, 0x5c, 0x71, 0x58, 0x3f, 0x9c, 0xca,
			0x96, 0x8e, 0xfd, 0x90, 0x88, 0xf6, 0x3a, 0x23, 0xdb, 0xf0,
			0xca, 0x5a, 0x4a, 0x8e, 0x29, 0x42, 0xdb, 0xa8, 0x87, 0x74,
			0xd4, 0xae, 0x9a, 0x6d, 0xf5, 0x6e, 0x00, 0xda, 0x0a, 0x03,
			0x17, 0xa3, 0x3a, 0xa5, 0xd1, 0x13, 0x9e, 0x81, 0xf2, 0xc8,
			0xf7, 0x07, 0xfa, 0xe8, 0x83, 0x1a, 0x00, 0x56, 0xd2, 0xf2,
			0x80, 0x6a, 0xe4, 0xf1, 0x4e, 0xda, 0x56, 0x66, 0xeb, 0xaf,
			0xad, 0x0c, 0x19, 0xe8, 0x30, 0xb3, 0x8b, 0x59, 0x9c, 0xbf,
			0x10, 0x38, 0xa7, 0xaf, 0x2a, 0xd3, 0x52, 0xae, 0xb0, 0x6e,
			0x3a, 0x01, 0x3f, 0xc9, 0x13, 0xdb, 0x99, 0xe5, 0xb5, 0x59,
			0x2b, 0x14, 0x48, 0xf3, 0xb5, 0x93, 0x38, 0xa8, 0x12, 0x98,
			0x6c, 0x83, 0x88, 0x32, 0x7a, 0x46, 0x46, 0xae, 0xed, 0x81,
			0x1c, 0xba, 0xab, 0xb3, 0x2e, 0xa0, 0x53, 0x57, 0x8c, 0x24,
			0x80, 0x7b, 0x9d, 0x74, 0xb9, 0xf5, 0x52, 0x01, 0x4f, 0x4c,
			0x51, 0x21, 0x1c, 0x4b, 0x6a, 0xe3, 0x00, 0x3e, 0x4c, 0xcb,
			0x40, 0xf8, 0xf4, 0x31, 0x8a, 0xa0, 0xbf, 0xf0, 0x4c, 0x02,
			0x7d, 0x47, 0x2d, 0x37, 0xe8, 0x6b, 0x20, 0xec, 0xef, 0xf1,
			0xb0, 0xaf, 0x87, 0x31, 0x06, 0x76, 0x1b, 0x59, 0x9a, 0x92,
			0xfa, 0x94, 0x7a, 0x76, 0xf5, 0x6f, 0x16, 0xde, 0x96, 0xb6,
			0x0e, 0xe0, 0x59, 0x09, 0x1e, 0x0f, 0xf7, 0x27, 0x59, 0xf5,
			0xe4, 0x01, 0x57, 0x88, 0x6c, 0x32, 0x73, 0x68, 0xbb, 0x63,
			0xe0, 0x3b, 0x57, 0xbd, 0xc5, 0x40, 0xbf, 0x5d, 0x8a, 0xd6,
			0x3c, 0x13, 0x40, 0x89, 0x74, 0x87, 0x82, 0xdb, 0x13, 0x90,
			0x0f, 0x42, 0x91, 0x8c, 0x35, 0xdf, 0x1f, 0x2a, 0xb1, 0x36,
			0x73, 0x49, 0x26, 0x40, 0x35, 0x5e, 0x60, 0xa8, 0x58, 0x23,
			0xe6, 0x14, 0x9d, 0x51, 0x61, 0x7c, 0x6f, 0x82, 0x88, 0x4f,
			0x96, 0xba, 0xe2, 0x7a, 0x14, 0x65, 0x26, 0xdb, 0xf5, 0xc2,
			0x8a, 0x07, 0xbc, 0x42, 0x2d, 0x33, 0x0f, 0x94, 0xfa, 0xdd,
			0x1a, 0xe7, 0x54, 0xda, 0x08, 0x1d, 0xdf, 0xb6, 0x03, 0x5c,
			0x51, 0x7e, 0xcf, 0xf8, 0x8f, 0x21, 0xd1, 0xad, 0x29, 0x6c,
			0x29, 0xee, 0x5a, 0x90, 0xf2, 0x0f, 0xd5, 0xe5, 0x29, 0x2e,
			0x98, 0x2e, 0x36, 0x0e, 0x97, 0x42, 0x73, 0x9c, 0xc1, 0x54,
			0x02, 0x2f, 0xde, 0xb1, 0x86, 0x3b, 0x69, 0x77, 0xe2, 0xc5,
			0xa8, 0x71, 0xc8, 0x11, 0x6e, 0x64, 0x33, 0x87, 0xa2, 0x17,
			0xfc, 0x84, 0x5e, 0x20, 0x0b, 0xc9, 0x25, 0x0c, 0xcb, 0x7f,
			0xe2, 0xfe, 0x18, 0x02, 0x59, 0x4a, 0x58, 0x41, 0xe1, 0x47,
			0xcc, 0xdf, 0x00, 0x51, 0x6d, 0x78, 0xa5, 0x81, 0x8b, 0x7b,
			0x24, 0x32, 0x7d, 0x39, 0x9a, 0xed, 0x4c, 0xc3, 0x7a, 0x8d,
			0x64, 0xe9, 0x6f, 0xdb, 0x24, 0x25, 0xa7, 0x99, 0x44, 0xca,
			0x99, 0x46, 0xa1, 0x48, 0x3b, 0x78, 0x31, 0xf8, 0x7d, 0x49,
			0x02, 0x4f, 0x07, 0x7d, 0x13, 0x9e, 0x16, 0x03, 0x3a, 0xec,
			0x32, 0x44, 0x6a, 0x8d, 0x9b, 0xbd, 0xf0, 0xf3, 0x01, 0xf2,
			0xa6, 0x3d, 0x84, 0x54, 0xb5, 0x8b, 0xe3, 0x84, 0xe3, 0xa5,
			0x15, 0xe3, 0x18, 0xef, 0x76, 0xd1, 0xd0, 0x02, 0x10, 0xfd,
			0x47, 0xdf, 0xe6, 0x32, 0x8f, 0xca, 0xa9, 0x0d, 0xa0, 0xa7,
			0x55, 0xaa, 0x4a, 0xee, 0x99, 0x8c, 0x8f, 0x52, 0x0e, 0xd3,
			0x24, 0xc7, 0x4f, 0x50, 0xc9, 0x4e, 0x69, 0xc8, 0x53, 0xc7,
			0xb1, 0x5f, 0x2e, 0x4f, 0xb3, 0xc5, 0x08, 0xfa, 0x9a, 0x29,
			0x30, 0x5e, 0x9c, 0x38, 0xcf, 0x83, 0xb9, 0xbf, 0x38, 0x4c,
			0x23, 0xe2, 0xc4, 0x1e, 0x7f, 0x96, 0x6c, 0xfc, 0x82, 0x50,
			0xb1, 0x9e, 0xbc, 0xe8, 0xcf, 0xa7, 0x3c, 0x16, 0x5f, 0x6f,
			0x8e, 0xda, 0xbc, 0x30, 0xc5, 0xbf, 0x78, 0xeb, 0xa8, 0xe7,
			0x4f, 0xd3, 0x12, 0x6a, 0xb2, 0xa3, 0xc1, 0x0b, 0x15, 0x3a,
			0xe0, 0x1d, 0x3e, 0x4e, 0xdd, 0x19, 0x6b, 0xfc, 0xca, 0x5c,
			0xdd, 0x48, 0xbf, 0xf1, 0x37, 0x02, 0x2d, 0x3c, 0xeb, 0xda,
			0x01, 0xb1, 0x60, 0x0c, 0x08, 0x99, 0xb5, 0x41, 0x10, 0x52,
			0x2b, 0x90, 0x50, 0xac, 0xe3, 0x48, 0x5a, 0xac, 0x6f, 0x5e,
			0x00, 0x2d, 0xeb, 0x78, 0x17, 0x36, 0xf8, 0x8f, 0x11, 0x9e,
			0x28, 0xe7, 0x58, 0x4f, 0x82, 0xcb, 0xce, 0x02, 0x57, 0x4e,
			0xee, 0xcc, 0xe9, 0x87, 0x69, 0x39, 0xe3, 0x2c, 0x2c, 0xdf,
			0xe4, 0xcd, 0xfc, 0x4e, 0xaf, 0xa8, 0xe5, 0x95, 0x20, 0x58,
			0x4f, 0x3c, 0x61, 0xe7, 0xba, 0xf3, 0xbe, 0x2a, 0x34, 0xd8,
			0x40, 0x16, 0xd3, 0xf7, 0x2d, 0xd6, 0x3f, 0x9a, 0x4e, 0x34,
			0x6b, 0x82, 0x6d, 0x47, 0x99, 0x14, 0x42, 0x9c, 0xc9, 0xea,
			0x3c, 0xfe, 0xaa, 0x12, 0x1f, 0xe2, 0x7f, 0xbd, 0x0d, 0x50,
			0x99, 0x9b, 0x49, 0x64, 0x04, 0x77, 0x86, 0x6d, 0xaa, 0xbd,
			0xa7, 0x83, 0xe7, 0x9d, 0x1a, 0xdd, 0x52, 0x1c, 0x5e, 0xbb,
			0x75, 0x04, 0x96, 0xca, 0xdc, 0xaa, 0x49, 0xe0, 0x66, 0x74,
			0x30, 0x8b, 0xe9, 0x35, 0x5d, 0xfc, 0x92, 0x9c, 0x0b, 0x38,
			0xcb, 0xbd, 0xff, 0x93, 0xe5, 0xc1, 0xeb, 0xcf, 0x87, 0x2a,
			0x17, 0x3e, 0xda, 0xc5, 0xa1, 0x12, 0xe5, 0x81, 0xd5, 0x20,
			0x31, 0x29, 0xe9, 0xd3, 0x31, 0x92, 0x1b, 0x20, 0x5a, 0x1d,
			0x65, 0xd3, 0xa8, 0x25, 0x68, 0xe8, 0xa2, 0x39, 0xc3, 0xfa,
			0xde, 0x6f, 0xfc, 0x04, 0x8b, 0x23, 0xa8, 0xf9, 0xd1, 0xee,
			0x54, 0x83, 0x82, 0xc6, 0x48, 0xa2, 0x59, 0x74, 0x80, 0xcf,
			0xb7, 0x9f, 0x4a, 0x01, 0x1e, 0xe5, 0x03, 0x30, 0x43, 0xb3,
			0x0c, 0x05, 0x14, 0x87, 0x7a, 0x04, 0x06, 0x8b, 0x5f, 0x92,
			0x36, 0x4b, 0x0b, 0xe9, 0x2c, 0x00, 0x08, 0x6f, 0xb9, 0x77,
			0xc3, 0x9c, 0x0e, 0xb8, 0x43, 0x01, 0x8f, 0xe9, 0x53, 0x8c,
			0x46, 0xdf, 0x94, 0x63, 0x87, 0x94, 0xee, 0xe2, 0xed, 0xab,
			0xf5, 0xf0, 0x70, 0xac, 0xad, 0x06, 0x53, 0x59, 0x8b, 0x0c,
			0x67, 0x47, 0xee, 0xb4, 0x26, 0x95, 0xe9, 0x46, 0x89, 0xe6,
			0x1c, 0xa2, 0x08, 0xe9, 0xc5, 0x06, 0xe1, 0x16, 0x39, 0xfd,
			0xb2, 0x46, 0xa3, 0x7e, 0x91, 0xc7, 0x56, 0x49, 0xda, 0xaa,
			0x32, 0x7a, 0xe9, 0x80, 0x3d, 0x8c, 0xe9, 0x41, 0x75, 0xe9,
			0xc6, 0x1f, 0xbb, 0xf7, 0x6e, 0xe9, 0x13, 0x74, 0x7b, 0x3f,
			0xd1, 0x68, 0xd1, 0xa1, 0x7a, 0x66, 0x66, 0x07, 0x0e, 0xa4,
			0x0e, 0xd3, 0xff, 0x9b, 0x75, 0x75, 0x34, 0xbe, 0xa8, 0x1c,
			0xb1, 0xc4, 0x00, 0x6e, 0x6e, 0x32, 0x2d, 0x49, 0xfe, 0xa0,
			0x14, 0xc6, 0x55, 0x4c, 0x36, 0x40, 0x79, 0x16, 0xd0, 0xd5,
			0x17, 0xb0, 0xfa, 0xf8, 0xe2, 0xed, 0xac, 0x12, 0x7d, 0x1e,
			0x27, 0xba, 0x89, 0x5a, 0xde, 0x9a, 0xeb, 0xf1, 0x2e, 0x3f,
			0x3f, 0x7f, 0xf7, 0x99, 0x70, 0xd7, 0x2d, 0xf2, 0xe2, 0xee,
			0x05, 0xd1, 0xd2, 0xd9, 0x7f, 0x70, 0xdc, 0x19, 0xc4, 0x6f,
			0x7a, 0x5c, 0xb0, 0x45, 0x17, 0x17, 0x57, 0x92, 0xf6, 0xab,
			0xbe, 0x28, 0x19, 0x48, 0x8f, 0x97, 0x76, 0xdf, 0xc4, 0x44,
			0x0a, 0x1b, 0xe7, 0xa5, 0xb2, 0x70, 0x92, 0x64, 0x15, 0x99,
			0x09, 0xbb, 0xbb, 0xe9, 0x02, 0x56, 0x54, 0xb0, 0xe8, 0x49,
			0xf6, 0x98, 0xcd, 0x58, 0x7a, 0xb2, 0x5f, 0xc4, 0x9d, 0x54,
			0xa4, 0x75, 0xfd, 0x49, 0x60, 0xf1, 0x8d, 0xbf, 0x2c, 0x23,
			0x13, 0xa6, 0xb9, 0x6c, 0x87, 0x5a, 0x2d, 0xb8, 0x42, 0xa6,
			0x84, 0x99, 0x55, 0x33, 0x2e, 0x15, 0x5e, 0xd4, 0xc9, 0xf3,
			0xd3, 0xb9, 0xe8, 0x71, 0xf6, 0xc6, 0x49, 0xac, 0x6d, 0x0c,
			0x63, 0xec, 0xf0, 0xf9, 0x48, 0x78, 0x45, 0xba, 0x50, 0xac,
			0xa8, 0xfe, 0x94, 0x3c, 0x53, 0x18, 0x8b, 0x2e, 0xc6, 0x9d,
			0x6c, 0x09, 0x13, 0xf1, 0x19, 0x4d, 0xcd, 0x0e, 0xb0, 0x75,
			0xc0, 0x48, 0x19, 0xaa, 0xb1, 0x13, 0x5f, 0xb8, 0x7f, 0xe9,
			0x8d, 0xe8, 0x1f, 0xd2, 0x6a, 0xf4, 0x80, 0x42, 0xd4, 0x9c,
			0x34, 0x10, 0xc2, 0xc4, 0xe2, 0x08, 0x1a, 0x6d, 0xbc, 0x2e,
			0x2a, 0x82, 0x36, 0x32, 0x95, 0x0d, 0x25, 0xaf, 0xed, 0xca,
			0x17, 0xb2, 0x42, 0x86, 0x76, 0x76, 0x40, 0x88, 0x56, 0x5d,
			0xe3, 0x41, 0x62, 0x8f, 0xc3, 0x64, 0xac, 0xe7, 0x8e, 0x39,
			0x0a, 0xe1, 0xc1, 0x9d, 0x4b, 0x01, 0x9c, 0xe9, 0xda, 0x67,
			0xef, 0x7f, 0x6c, 0xd3, 0xa0, 0x27, 0xc1, 0xab, 0xbe, 0xa6,
			0xa5, 0x19, 0x27, 0x5a, 0x55, 0x35, 0x70, 0xe7, 0xf5, 0xa0,
			0xfa, 0x0a, 0xce, 0x93, 0xea, 0xd4, 0xbf, 0xbd, 0x08, 0x20,
			0x01, 0x76, 0x1d, 0x65, 0x1e, 0x1d, 0x6e, 0x28, 0x0e, 0x1c,
			0x22, 0x43, 0xf3, 0x25, 0x77, 0x7c, 0xe4, 0x3b, 0x3a, 0x1f,
			0x04, 0x77, 0x19, 0x88, 0x57, 0xf1, 0x89, 0x14, 0xba, 0x05,
			0xf0, 0x38, 0x87, 0x48, 0xb3, 0x62, 0x5d, 0x8d, 0x79, 0xe7,
			0x7f, 0x07, 0x7c, 0x7f, 0xaf, 0x31, 0x86, 0x51, 0x8d, 0x89,
			0x2d, 0x50, 0x6f, 0xab, 0xf6, 0x41, 0xb1, 0xc9, 0x24, 0x6b,
			0x32, 0xf4, 0xe0, 0x89, 0xec, 0x4e, 0xbe, 0x9b, 0x15, 0xf4,
			0xa4, 0xd3, 0x0b, 0x49, 0x8c, 0xd4, 0x9a, 0x81, 0xa8, 0x03,
			0x79, 0x2d, 0xfe, 0xa7, 0x6d, 0x32, 0x22, 0x43, 0xcc, 0xa5,
			0xeb, 0x8b, 0xf5, 0x20, 0xc7, 0x73, 0x2d, 0xa0, 0xc8, 0x88,
			0x27, 0xe3, 0x1f, 0xa6, 0x03, 0x3a, 0x8f, 0xf6, 0x31, 0xda,
			0x31, 0x09, 0x5e, 0xd6, 0xe0, 0x7f, 0xc4, 0xa9, 0xa4, 0x58,
			0x50, 0xfe, 0xb9, 0x15, 0x78, 0xc6, 0xb3, 0x52, 0xeb, 0xe1,
			0x09, 0x21, 0x2d, 0xaf, 0x09, 0xf8, 0xea, 0xfa, 0xb2, 0x85,
			0x55, 0x8e, 0x2d, 0xc3, 0xc3, 0x3b, 0xd7, 0xa8, 0x97, 0x9d,
			0x16, 0x78, 0x50, 0x52, 0x86, 0x3a, 0xf3, 0xc6, 0xbe, 0xe6,
			0xbd, 0xdb, 0xa4, 0x9a, 0x24, 0x80, 0xb0, 0xc9, 0x70, 0x91,
			0x29, 0xe4, 0x52, 0xf5, 0xb5, 0x08, 0x7b, 0x54, 0x01, 0xd8,
			0x0e, 0x61, 0xe6, 0x6b, 0xf8, 0x55, 0xcf, 0x26, 0x53, 0xa4,
			0x61, 0x5b, 0xeb, 0x3d, 0x73, 0x88, 0x7e, 0x59, 0x3d, 0x8b,
			0x23, 0xae, 0x6c, 0x4b, 0xf5, 0x93, 0x5e, 0xc6, 0xf6, 0x2d,
			0x37, 0x9f, 0x62, 0x25, 0xf6, 0xcc, 0x85, 0x3c, 0x16, 0xc3,
			0x94, 0x66, 0xd8, 0xd8, 0x52, 0x6d, 0xa8, 0x69, 0x1e, 0x28,
			0xa6, 0xe1, 0x7d, 0xc7, 0x86, 0xa1, 0xe4, 0x5d, 0x01, 0xeb,
			0xb9, 0x09, 0xd8, 0xec, 0x2a, 0x6e, 0x21, 0xc9, 0x29, 0x1f,
			0xc8, 0x85, 0xc0, 0x7f, 0x43, 0xb6, 0x32, 0x3a, 0x69, 0xaf,
			0xc5, 0x0b, 0xa5, 0x86, 0xd8, 0x1b, 0xa3, 0x2a, 0xeb, 0x12,
			0x31, 0xdd, 0xe7, 0x54, 0xb7, 0xc5, 0x6d, 0x10, 0xcf, 0x83,
			0xdc, 0x38, 0x0a, 0x6c, 0xef, 0xa4, 0x90, 0xb3, 0x4a, 0x0e,
			0xd2, 0xdc, 0x69, 0xbb, 0x88, 0x58, 0x16, 0x2d, 0xb2, 0xfe,
			0xa1, 0x16, 0x74, 0x70, 0x31, 0x70, 0x25, 0x0e, 0x11, 0x2e,
			0x3e, 0x81, 0x35, 0xff, 0x39, 0x23, 0xb2, 0x7a, 0xb3, 0x2e,
			0x99, 0xd9, 0x2c, 0x6b, 0xd9, 0xce, 0x48, 0x22, 0x71, 0xb2,
			0x25, 0x66, 0x70, 0x17, 0x0a, 0xf1, 0x18, 0xeb, 0x70, 0x77,
			0x35, 0x9e, 0xbb, 0xe7, 0x16, 0xb9, 0x59, 0x90, 0xb3, 0x38,
			0x03, 0x8c, 0x17, 0x41, 0xdd, 0x74, 0x50, 0x2a, 0x17, 0x95,
			0x4b, 0xf1, 0x9b, 0xfe, 0xbe, 0x65, 0x89, 0xa1, 0x0a, 0xfe,
			0x47, 0xf5, 0xdb, 0xff, 0x4b, 0x35, 0x5a, 0x1e, 0xb4, 0x36,
			0x92, 0x98, 0x75, 0x99, 0x43, 0x99, 0x50, 0x27, 0xe1, 0x7a,
			0xcb, 0x03, 0x64, 0x55, 0x4f, 0x18, 0x10, 0x60, 0x14, 0x58,
			0x30, 0x18, 0x71, 0x10, 0xa2, 0xe3, 0x87, 0xb0, 0xb1, 0xe9,
			0xa0, 0xee, 0x51, 0x88, 0x08, 0x12, 0x24, 0xda, 0x83, 0xb9,
			0xb1, 0xab, 0xc9, 0x9d, 0x90, 0x6e, 0xb0, 0x21, 0xec, 0x80,
			0xfe, 0x11, 0x80, 0xda, 0x6f, 0xcb, 0xa7, 0x99, 0x3e, 0xc9,
			0x9b, 0x75, 0xbf, 0x33, 0x10, 0x06, 0xca, 0x01, 0xd0, 0x99,
			0x75, 0x63, 0x41, 0xed, 0x04, 0xfe, 0xf0, 0x6e, 0x3a, 0x0c,
			0x30, 0x64, 0xf7, 0x31, 0x9e, 0x19, 0x43, 0x7c, 0x3b, 0x52,
			0x30, 0x62, 0x7d, 0x07, 0xd1, 0xec, 0xa8, 0x50, 0x29, 0xaf,
			0x67, 0x46, 0x88, 0xf5, 0x5e, 0x7d, 0x22, 0xcc, 0xdc, 0x4b,
			0x9c, 0x31, 0x12, 0xa2, 0x18, 0xfc, 0xd3, 0x57, 0xc6, 0x60,
			0x5f, 0xad, 0x41, 0x49, 0x8c, 0xdb, 0x62, 0xe8, 0xda, 0x05,
			0x4e, 0x0f, 0x5a, 0x90, 0x3c, 0x6b, 0x06, 0x70, 0x18, 0xb0,
			0x8e, 0x43, 0x49, 0xf2, 0xa6, 0x34, 0x96, 0xdb, 0xa7, 0x9c,
			0xc2, 0xc3, 0xdf, 0xdd, 0x9f, 0x0b, 0x88, 0xcc, 0xb1, 0x4d,
			0x57, 0x8c, 0x51, 0x3b, 0xba, 0x20, 0x53, 0xd0, 0xf5, 0x83,
			0xf9, 0x7d, 0x4d, 0x7b, 0xae, 0x64, 0xc9, 0xc2, 0x09, 0x74,
			0xcf, 0x6e, 0x79, 0x6a, 0x8c, 0x92, 0x9c, 0x16, 0x73, 0xd0,
			0xaa, 0x0c, 0x8d, 0x3f, 0x00, 0xbb, 0x36, 0xd2, 0x8f, 0x7a,
			0xa9, 0x5c, 0x30, 0x3a, 0x51, 0x9c, 0xd1, 0x25, 0x2f, 0xee,
			0x16, 0x7d, 0xb1, 0x02, 0xa9, 0x5b, 0x2f, 0x18, 0x10, 0xc2,
			0x5b, 0xf6, 0x13, 0x6e, 0x77, 0xd8, 0x8b, 0xc8, 0x3a, 0x3b,
			0x75, 0x44, 0xb6, 0x9b, 0x8a, 0x31, 0x21, 0x4c, 0x25, 0x3f,
			0xcd, 0x4e, 0x50, 0x2b, 0xe0, 0xd5, 0x49, 0x3b, 0x0c, 0xc8,
			0x3b, 0xe0, 0x12, 0xb0, 0xf6, 0xff, 0xe1, 0xa9, 0xfd, 0xdb,
			0x19, 0x06, 0x2a, 0x4c, 0x83, 0xff, 0xb2, 0x63, 0x13, 0x85,
			0x06, 0xfc, 0xd5, 0x4c, 0x5a, 0x57, 0x34, 0x79, 0xe6, 0xc6,
			0x20, 0x9b, 0x21, 0x0e, 0x50, 0x7c, 0x9f, 0xb4, 0x10, 0xa9,
			0xa4, 0xa3, 0x3c, 0x43, 0x84, 0x16, 0x4c, 0x3d, 0xb3, 0x53,
			0xc2, 0x12, 0xfd, 0x21, 0x32, 0xf8, 0x42, 0x69, 0x64, 0x9e,
			0xd1, 0x42, 0x65, 0xbb, 0x86, 0x7c, 0x9b, 0xcb, 0xfd, 0xac,
			0xdc, 0xe5, 0xba, 0xd6, 0xa9, 0x84, 0xca, 0x8e, 0x39, 0x2a,
			0x9c, 0x69, 0x3e, 0x1a, 0x0d, 0xe7, 0xc9, 0xcd, 0xd0, 0x23,
			0x2e, 0xfb, 0xcd, 0xf8, 0x63, 0x56, 0x51, 0x13, 0x63, 0x9f,
			0xaa, 0x8c, 0x7e, 0x06, 0xc2, 0xdc, 0xff, 0x9d, 0x6a, 0x74,
			0x6a, 0xd5, 0x9b, 0xb5, 0x70, 0x4a, 0xda, 0xc4, 0x39, 0xda,
			0xa2, 0x31, 0x6e, 0x54, 0x38, 0xec, 0xd5, 0x82, 0xff, 0x78,
			0xae, 0x8b, 0x92, 0x84, 0xbf, 0x69, 0x1e, 0x4c, 0x7e, 0x05,
			0x31, 0x22, 0x8a, 0xcd, 0xd7, 0x93, 0xa6, 0x11, 0x34, 0xb9,
			0x6b, 0x57, 0xbd, 0xe2, 0xa2, 0x66, 0xd5, 0x6e, 0x0a, 0x4f,
			0xd4, 0x3b, 0xc6, 0x6c, 0x19, 0xcf, 0x6e, 0x4a, 0xeb, 0xbc,
			0x0d, 0x51, 0x36, 0x5d, 0xcb, 0x52, 0xe9, 0xb1, 0xa5, 0x18,
			0x2d, 0x90, 0x45, 0xfd, 0x94, 0x5a, 0x54, 0xa2, 0x5b, 0xbe,
			0xbd, 0xd6, 0x66, 0xcf, 0x69, 0xba, 0x58, 0x24, 0xda, 0x20,
			0x4d, 0x6b, 0x5f, 0x52, 0x5b, 0x35, 0x9e, 0xa8, 0x0b, 0x09,
			0x1d, 0x80, 0x3f, 0x23, 0xb5, 0x0c, 0x25, 0xa9, 0x2e, 0x89,
			0xf1, 0x42, 0x5a, 0xd1, 0x03, 0xbf, 0x79, 0xcf, 0x01, 0x8d,
			0xab, 0x4d, 0x94, 0x5a, 0xce, 0xc1, 0x7f, 0x4c, 0x6c, 0x96,
			0x34, 0xf5, 0x7c, 0xdb, 0x04, 0x15, 0xf3, 0x85, 0xa9, 0xd8,
			0xb4, 0x8a, 0x5f, 0x14, 0x32, 0x53, 0x35, 0x47, 0x57, 0xd7,
			0xa6, 0x95, 0x80, 0x50, 0x09, 0xcf, 0x90, 0x23, 0x4a, 0xd2,
			0x63, 0x09, 0x80, 0xa9, 0xe2, 0xf8, 0xc7, 0x0d, 0x02, 0x39,
			0xc1, 0xd1, 0x3a, 0x09, 0x04, 0x81, 0x10, 0x26, 0x0a, 0x6a,
			0x4e, 0x56, 0xe4, 0x29, 0xdf, 0x82, 0x66, 0x35, 0x0c, 0x0e,
			0x19, 0x17, 0x6f, 0x01, 0x24, 0x08, 0xf1, 0x0a, 0x81, 0x3b,
			0x89, 0x7e, 0x9c, 0x4a, 0xac, 0xb7, 0xbc, 0x59, 0x2a, 0x43,
			0xa9, 0x8a, 0xbd, 0x83, 0xdb, 0x89, 0x81, 0x57, 0xd7, 0x71,
			0x10, 0x17, 0x7e, 0x2a, 0x8a, 0x2e, 0x23, 0x66, 0x69, 0x71,
			0x3b, 0xad, 0x7c, 0x30, 0x82, 0x1e, 0xb5, 0xcc, 0xc6, 0xe7,
			0xf5, 0x29, 0x37, 0xdf, 0xf3, 0x26, 0x1a, 0x9f, 0x63, 0x72,
			0x91, 0x80, 0x10, 0x4e, 0x36, 0x1e, 0xf5, 0x3d, 0x05, 0xbd,
			0x1d, 0xac, 0x97, 0x34, 0xec, 0x95, 0x21, 0x92, 0x2f, 0x9d,
			0x1b, 0x0e, 0xfe, 0x60, 0x78, 0x78, 0x39, 0xf6, 0xe2, 0xad,
			0x58, 0x33, 0x0e, 0x1a, 0xe9, 0x2e, 0x13, 0x1d, 0xe5, 0x36,
			0xee, 0x8b, 0x25, 0x4d, 0x66, 0x3e, 0x71, 0x6e, 0x93, 0xcb,
			0x1f, 0x67, 0xe7, 0xdd, 0x25, 0x21, 0x48, 0xee, 0xc2, 0xed,
			0x2a, 0x3b, 0x68, 0x7b, 0x82, 0xb7, 0xea, 0xc2, 0xc0, 0xd4,
			0x3f, 0xa7, 0xdd, 0x67, 0x43, 0xb5, 0x7a, 0xe9, 0x08, 0xab,
			0x26, 0xa1, 0xae, 0xd1, 0x52, 0x3e, 0xd6, 0xee, 0x21, 0x09,
			0xb7, 0xe2, 0xb8, 0x30, 0xa9, 0x20, 0x7a, 0xd9, 0x26, 0xbc,
			0xe4, 0x60, 0xf1, 0x79, 0x1e, 0xea, 0xe8, 0xaa, 0xaf, 0x1e,
			0x09, 0x0f, 0x3b, 0x5e, 0x7b, 0x1f, 0x25, 0xae, 0x83, 0x3c,
			0x69, 0xb7, 0x8f, 0xed, 0x7e, 0x6d, 0xb5, 0xeb, 0x9c, 0x80,
			0xee, 0x01, 0x7c, 0x54, 0xa9, 0x12, 0x2f, 0x42, 0xe5, 0xc0,
			0x3a, 0x48, 0xa8, 0xa7, 0x00, 0x97, 0x8a, 0x1d, 0x03, 0x04,
			0x06, 0xb4, 0x30, 0x79, 0x77, 0x27, 0x89, 0x3a, 0x25, 0xac,
			0x8b, 0xde, 0x9b, 0x4f, 0x27, 0x3c, 0xa6, 0x70, 0x88, 0x61,
			0x76, 0x3a, 0xfe, 0x4e, 0xba, 0xeb, 0xcb, 0xc6, 0x67, 0xd7,
			0xb9, 0xed, 0xa5, 0x5e, 0x61, 0xe8, 0x50, 0x6f, 0x97, 0x73,
			0x5b, 0x07, 0xfb, 0xd7, 0xac, 0x8c, 0xde, 0xcf, 0xec, 0x73,
			0x7b, 0x8c, 0x84, 0xce, 0x35, 0x6a, 0x81, 0x54, 0xee, 0x2b,
			0x3b, 0x01, 0xea, 0x29, 0x35, 0x6c, 0x09, 0x27, 0x14, 0xc0,
			0x04, 0x93, 0xb4, 0x7e, 0x59, 0xd6, 0x8d, 0x00, 0xdd, 0x46,
			0xa3, 0x08, 0x4e, 0x9f, 0x89, 0x81, 0xd8, 0x1e, 0xf2, 0xbc,
			0x04, 0x4d, 0xa4, 0x41, 0xe7, 0xd7, 0x82, 0xa6, 0x90, 0x31,
			0xfa, 0x91, 0xf6, 0xa7, 0x19, 0x35, 0xea, 0x09, 0x0a, 0xd2,
			0x9c, 0x18, 0xd6, 0x3b, 0xb9, 0xfe, 0xfe, 0xcc, 0x9b, 0x69,
			0xbb, 0x14, 0x78, 0xc5, 0xef, 0xa4, 0x8d, 0xd9, 0x46, 0xef,
			0x47, 0x80, 0x1d, 0xf9, 0x3b, 0xd6, 0xc5, 0x0f, 0xee, 0xb5,
			0x93, 0x0a, 0x21, 0x10, 0x77, 0xd1, 0x27, 0x51, 0xc2, 0xa9,
			0xe7, 0x52, 0xa5, 0x1f, 0x66, 0x25, 0x80, 0xdb, 0x5d, 0x17,
			0x02, 0xbb, 0x34, 0x1e, 0x46, 0x42, 0x32, 0x96, 0xdd, 0x7f,
			0xa4, 0xac, 0xfc, 0x5a, 0xf5, 0x09, 0xe7, 0x92, 0x53, 0xeb,
			0x88, 0xdc, 0x33, 0x88, 0x53, 0x68, 0xf4, 0x5f, 0xd7, 0xed,
			0xa4, 0xb7, 0x88, 0x9f, 0x0c, 0x67, 0x86, 0xb9, 0x96, 0xc7,
			0x0a, 0xe5, 0x6b, 0xac, 0x89, 0xb0, 0x31, 0x68, 0x4c, 0x9c,
			0xf0, 0x55, 0xcb, 0x70, 0x53, 0x22, 0x8e, 0xca, 0xee, 0x33,
			0xc6, 0x43, 0xff, 0xde, 0xdf, 0xe3, 0x30, 0x8a, 0xbe, 0x7c,
			0x88, 0xf1, 0x3e, 0x29, 0xd6, 0x1b, 0x07, 0x43, 0xbd, 0x4b,
			0xc8, 0x51, 0xe6, 0x8e, 0x17, 0x45, 0x98, 0xb9, 0x1f, 0xf9,
			0xdb, 0xcd, 0x52, 0x52, 0xc2, 0x47, 0x12, 0xfc, 0x51, 0x57,
			0x63, 0x3a, 0xbf, 0x7c, 0x2e, 0xd4, 0xb1, 0x09, 0x69, 0x39,
			0x8d, 0xb7, 0x15, 0x2a, 0xcb, 0x89, 0xcb, 0x28, 0x67, 0xcf,
			0xa7, 0x4a, 0x0b, 0xb8, 0x3d, 0x10, 0x30, 0xd5, 0x4a, 0xd9,
			0xea, 0x42, 0x83, 0x4e, 0x2a, 0x8d, 0x38, 0xf9, 0xc8, 0xe8,
			0x33, 0xa1, 0x09, 0xd9, 0xf0, 0x75, 0xde, 0xe3, 0xc2, 0x42,
			0x8f, 0x49, 0xd8, 0x7c, 0x7f, 0x47, 0xfb, 0x0c, 0xc1, 0x2e,
			0x66, 0x01, 0x09, 0x96, 0x0c, 0x56, 0x72, 0x66, 0x3e, 0x38,
			0x4a, 0xb4, 0xcd, 0xc4, 0xd0, 0x4e, 0x82, 0xce, 0xac, 0x5f,
			0x40, 0x3b, 0x59, 0x80, 0x84, 0xc6, 0x9b, 0x43, 0xc4, 0x9b,
			0xd6, 0x4f, 0x91, 0x74, 0x3f, 0xdd, 0x78, 0xf0, 0xe5, 0xd8,
			0xbe, 0x71, 0x21, 0xb7, 0x11, 0x05, 0x09, 0x77, 0x87, 0xd9,
			0x06, 0xc9, 0x04, 0xc0, 0xb9, 0x2c, 0x59, 0xdb, 0x2b, 0xbc,
			0x22, 0x17, 0xcb, 0xef, 0x93, 0xe8, 0xfb, 0x5c, 0x2a, 0x74,
			0x70, 0x9f, 0x9d, 0x45, 0x0c, 0xe9, 0xec, 0xfe, 0x57, 0x44,
			0x22, 0x1a, 0xc8, 0xb5, 0x9d, 0xbc, 0x8b, 0x75, 0x5d, 0x8d,
			0x3d, 0xdb, 0xb1, 0x65, 0x01, 0x4c, 0x4a, 0xdd, 0x68, 0x06,
			0x39, 0x57, 0x15, 0x3c, 0x4a, 0x1c, 0x1a, 0x29, 0x88, 0xfa,
			0xe7, 0x68, 0x05, 0x9e, 0xc9, 0xc3, 0x95, 0x52, 0x51, 0x46,
			0xb9, 0xf3, 0x14, 0xb2, 0x21, 0x99, 0xd4, 0xbf, 0x5e, 0x64,
			0x58, 0xa9, 0x2f, 0x87, 0x84, 0x00, 0x4e, 0x8c, 0x6b, 0x86,
			0xa7, 0xb6, 0x72, 0x40, 0xab, 0x49, 0xa7, 0x8f, 0x37, 0xc0,
			0x3c, 0xbc, 0xc1, 0xb0, 0xce, 0x28, 0x2a, 0x40, 0xd7, 0x17,
			0xcd, 0x18, 0x29, 0xf7, 0x40, 0xa9, 0xd4, 0x2b, 0xe5, 0x38,
			0x59, 0xb7, 0xe2, 0xf3, 0xec, 0xe6, 0x3d, 0xa2, 0x2d, 0x70,
			0x92, 0x73, 0x41, 0x3b, 0x37, 0xe4, 0x21, 0x6c, 0x88, 0x1c,
			0xe3, 0xda, 0x08, 0x7d, 0xeb, 0xfb, 0xdb, 0x33, 0xaf, 0x0f,
			0xad, 0x72, 0x06, 0x8a, 0x60, 0x46, 0x3d, 0x30, 0x03, 0xe4,
			0x50, 0x8f, 0x2f, 0xf4, 0x33, 0xe3, 0x2b, 0x33, 0x2a, 0x31,
			0x70, 0x79, 0x07, 0xc0, 0x62, 0xca, 0xdc, 0xaa, 0xba, 0x74,
			0x9f, 0xac, 0xc0, 0xab, 0xa9, 0x5b, 0x8a, 0x2b, 0x40, 0xe9,
			0x34, 0x85, 0x12, 0x42, 0x24, 0xdf, 0x2c, 0xaa, 0x38, 0xc2,
			0x6f, 0x8c, 0x2c, 0x7a, 0x4c, 0x2e, 0xbd, 0x9c, 0x10, 0x5d,
			0x1a, 0x16, 0xf5, 0xce, 0x96, 0x17, 0xf4, 0x96, 0xa7, 0x30,
			0x05, 0xfa, 0x55, 0xfd, 0x31, 0xcc, 0xcc, 0xf0, 0x98, 0x51,
			0x18, 0x10, 0x06, 0x5c, 0x33, 0x4e, 0xde, 0xb3, 0xf6, 0x90,
			0x37, 0x6a, 0x03, 0x71, 0xe7, 0x3f, 0x21, 0x09, 0x10, 0x0f,
			0xaa, 0xa2, 0x23, 0x5b, 0xf9, 0x7a, 0x47, 0xfa, 0x68, 0xf3,
			0xcf, 0xae, 0xf2, 0x9a, 0x1d, 0xab, 0x8b, 0xac, 0x60, 0xe7,
			0xbd, 0xbc, 0x1f, 0xfa, 0x8c, 0x93, 0x26, 0x8a, 0x89, 0x58,
			0x4f, 0x0d, 0xf6, 0x70, 0x62, 0x96, 0xd5, 0x3b, 0x52, 0x53,
			0xa0, 0x44, 0x8f, 0x1a, 0x51, 0x56, 0x68, 0xc3, 0xf0, 0xc6,
			0xc3, 0x70, 0x64, 0xef, 0x92, 0x67, 0x42, 0x76, 0x96, 0xa1,
			0xec, 0x05, 0x7f, 0x34, 0x3b, 0x8f, 0x09, 0x4a, 0xe7, 0xc4,
			0x02, 0xcf, 0x51, 0xd4, 0x72, 0x5b, 0xa5, 0xae, 0xf6, 0xed,
			0xfa, 0xb9, 0xf8, 0xfd, 0xd7, 0xd4, 0x61, 0xb6, 0x54, 0x0e,
			0x9a, 0xbb, 0xc8, 0x94, 0x21, 0x67, 0x56, 0xe9, 0xbc, 0xcc,
			0x88, 0x5e, 0xd6, 0x93, 0xfd, 0xb8, 0xdd, 0x22, 0xea, 0x5f,
			0x4e, 0xdf, 0xf4, 0xf2, 0x8c, 0x9e, 0xa1, 0xf8, 0x49, 0x1f,
			0x42, 0x0e, 0x11, 0x83, 0xc6, 0x83, 0xa4, 0x23, 0xd6, 0x0d,
			0x14, 0x3e, 0x8b, 0x01, 0xc6, 0xec, 0xfb, 0x4b, 0xc8, 0xe2,
			0x51, 0xbf, 0x31, 0xcc, 0x2b, 0xfb, 0x16, 0x3f, 0x9e, 0x55,
			0x98, 0x95, 0x86, 0x65, 0xa4, 0x22, 0xe2, 0xc9, 0x72, 0x97,
			0x69, 0x0d, 0x2e, 0x5d, 0x87, 0x6a, 0x8e, 0x8a, 0x1b, 0xc3,
			0xbd, 0x19, 0xcd, 0xd2, 0xf9, 0x5b, 0xbf, 0xd1, 0x32, 0x11,
			0xdc, 0xdd, 0xd3, 0x9b, 0x41, 0x85, 0x7c, 0x38, 0x41, 0x6f,
			0x74, 0x4b, 0x0c, 0xc0, 0x17, 0x75, 0xee, 0x55, 0x5f, 0xeb,
			0x8e, 0xb7, 0x9d, 0xbf, 0x35, 0xda, 0xea, 0x07, 0x3c, 0xe5,
			0x7f, 0x22, 0x1c, 0x4d, 0x22, 0x1d, 0xe4, 0x4b, 0xc7, 0xe5,
			0x6a, 0x59, 0xdb, 0x9f, 0xb2, 0x79, 0xc1, 0xc9, 0x20, 0x97,
			0xe5, 0xcf, 0x2f, 0xc1, 0xb7, 0x5d, 0xb1, 0xbf, 0x6d, 0xca,
			0x7a, 0x34, 0x1d, 0x39, 0x88, 0x1c, 0x2d, 0x83, 0xd5, 0xf6,
			0xef, 0x4c, 0xce, 0xe7, 0x2e, 0x35, 0xcd, 0xab, 0x7d, 0x64,
			0xd6, 0x57, 0x93, 0x66, 0x7e, 0xab, 0x5b, 0xf2, 0xc9, 0x49,
			0xd8, 0x67, 0x97, 0x01, 0x72, 0x5a, 0xf2, 0xfa, 0x7d, 0x27,
			0x56, 0x88, 0x9f, 0xb0, 0xc1, 0x3c, 0x2c, 0x9d, 0x5a, 0x5f,
			0x96, 0x30, 0xee, 0x3a, 0x90, 0x74, 0xb0, 0x9f, 0x30, 0x9b,
			0x98, 0x86, 0xff, 0x15, 0x0e, 0xad, 0x55, 0x23, 0xbf, 0xc4,
			0xb3, 0x21, 0xfc, 0x1d, 0x45, 0x5c, 0x12, 0x78, 0xa4, 0x63,
			0xe2, 0x05, 0xda, 0x25, 0x82, 0xbb, 0x7f, 0xa3, 0x1f, 0xc7,
			0x2b, 0x1c, 0xbd, 0x6c, 0x34, 0xe0, 0xc9, 0xf1, 0x44, 0x70,
			0xec, 0x13, 0xb9, 0x73, 0x1c, 0x82, 0x45, 0x99, 0xe6, 0xb1,
			0xf0, 0x9f, 0xfa, 0x79, 0xa7, 0x6f, 0x3e, 0xf4, 0xd1, 0x18,
			0x90, 0x4b, 0xd2, 0xdb, 0x5a, 0x0f, 0x9f, 0x5d, 0x97, 0x67,
			0x52, 0x19, 0x19, 0x3c, 0x1c, 0x74, 0x40, 0x8c, 0x7b, 0xbf,
			0xfe, 0x02, 0x26, 0x66, 0x46, 0xab, 0x3f, 0x46, 0x94, 0x56,
			0x47, 0x87, 0x11, 0xa0, 0x3d, 0x46, 0xfa, 0xae, 0xc9, 0x78,
			0x95, 0x36, 0x99, 0x98, 0xff, 0xe1, 0x59, 0x74, 0xc8, 0xa2,
			0x79, 0x61, 0x7e, 0x42, 0xed, 0x9a, 0x2f, 0x13, 0x1b, 0x8e,
			0x6b, 0x25, 0x53, 0x4d, 0xbf, 0xf8, 0x6a, 0x40, 0x97, 0x5c,
			0x52, 0x6b, 0xe8, 0x09, 0x5f, 0x3d, 0x4f, 0xfe, 0x8f, 0xdf,
			0x66, 0x10, 0x49, 0xd7, 0x05, 0x56, 0x9e, 0x32, 0x74, 0x3c,
			0x01, 0x1e, 0x50, 0x7d, 0x1a, 0xae, 0xed, 0xcc, 0x07, 0x6f,
			0x9c, 0x3b, 0x37, 0x9e, 0x82, 0x0f, 0xa5, 0x6e, 0x1e, 0x18,
			0x89, 0xda, 0xaa, 0xdb, 0x1a, 0xd4, 0xc7, 0x30, 0xd1, 0x54,
			0x42, 0x48, 0x08, 0xeb, 0x2f, 0x26, 0xd2, 0x09, 0x11, 0xa7,
			0x56, 0x27, 0xb0, 0x91, 0x9d, 0x16, 0x54, 0x6c, 0x6c, 0x50,
			0x56, 0x7e, 0xd2, 0xd8, 0xf9, 0x83, 0xe8, 0xa3, 0x8d, 0x52,
			0x0e, 0x42, 0x2f, 0xb5, 0x87, 0xd7, 0x4b, 0x9a, 0xf5, 0x91,
			0xf9, 0x41, 0x89, 0x79, 0x55, 0xfe, 0x14, 0x7b, 0x0a, 0xd8,
			0xe3, 0x83, 0xad, 0x02, 0x26, 0x3c, 0x4d, 0x08, 0xe4, 0x47,
			0x41, 0xc9, 0x36, 0x12, 0xdc, 0xc3, 0x53, 0x7e, 0xb6, 0xf7,
			0xed, 0x6c, 0x3f, 0x4a, 0x97, 0x98, 0x1d, 0xbe, 0x4e, 0x12,
			0x58, 0xc3, 0x1c, 0x1b, 0xfb, 0xd2, 0xf5, 0x16, 0x80, 0xd4,
			0xa9, 0x0b, 0xab, 0x86, 0xa5, 0xd4, 0xd8, 0x7f, 0x3f, 0xc4,
			0x71, 0xbb, 0x69, 0xc6, 0xd9, 0x9b, 0x72, 0x95, 0x6d, 0xf9,
			0x79, 0x52, 0x6b, 0xde, 0x65, 0x97, 0xe5, 0x5e, 0xd1, 0xc1,
			0xbd, 0x94, 0x53, 0xed, 0xf4, 0x4e, 0x6c, 0xd4, 0x7f, 0x3e,
			0xca, 0xd4, 0x0e, 0xb9, 0x9a, 0x56, 0x73, 0x56, 0xb2, 0xde,
			0x4c, 0x3c, 0x1c, 0xdf, 0x26, 0x14, 0x67, 0xb4, 0x67, 0x35,
			0x54, 0x4c, 0x45, 0x5e, 0x37, 0x55, 0xfd, 0x3b, 0x65, 0x5d,
			0xc7, 0xdd, 0x4d, 0xd5, 0x8b, 0x32, 0x43, 0xf7, 0xfc, 0xd6,
			0xbb, 0xb5, 0x98, 0x3d, 0x49, 0xe1, 0xac, 0x40, 0xc9, 0xd1,
			0xf5, 0x7b, 0x5f, 0x6d, 0x46, 0xea, 0x15, 0xaf, 0x3d, 0x02,
			0xbb, 0xe4, 0x98, 0x47, 0xd3, 0x70, 0xc5, 0xa8, 0x72, 0x8e,
			0xae, 0xd8, 0x23, 0x2d, 0xcf, 0x50, 0x5e, 0xa6, 0x7d, 0xbd,
			0x81, 0xd4, 0x11, 0x12, 0xbf, 0x7f, 0x37, 0xee, 0x5d, 0x39,
			0x4c, 0x0f, 0x92, 0xb0, 0x7e, 0x20, 0x3c, 0x71, 0x4e, 0x92,
			0x33, 0x46, 0xd6, 0xb2, 0xbf, 0xa4, 0x57, 0xcb, 0x0d, 0x4e,
			0xe8, 0x54, 0x07, 0x5b, 0x01, 0x15, 0x46, 0x61, 0xcc, 0x7d,
			0x9f, 0xa5, 0xab, 0x27, 0x34, 0x16, 0x45, 0x9c, 0x82, 0x0e,
			0x60, 0x97, 0x44, 0x8b, 0x0e, 0x36, 0x29, 0x58, 0x10, 0x07,
			0x97, 0x83, 0x33, 0x78, 0x27, 0xff, 0xee, 0xa0, 0x73, 0x3f,
			0xf4, 0x06, 0xec, 0x56, 0x11, 0xfc, 0xff, 0xc6, 0xee, 0x81,
			0x0a, 0xd5, 0x93, 0xb0, 0x41, 0x4e, 0xd3, 0xbf, 0xf7, 0xb8,
			0xa5, 0x81, 0x4c, 0xee, 0x7f, 0xdb, 0x48, 0x39, 0xed, 0x98,
			0x4e, 0x8c, 0xb9, 0xc6, 0x72, 0x85, 0xa2, 0x91, 0x7d, 0x2d,
			0x74, 0x96, 0xae, 0x8d, 0x4d, 0x8a, 0x77, 0xf2, 0xe6, 0xcc,
			0x20, 0x7e, 0x40, 0x31, 0x8a, 0xd6, 0xd1, 0xc4, 0xef, 0x74,
			0x7a, 0x5b, 0x2c, 0x74, 0x02, 0x3b, 0xe1, 0x12, 0x23, 0x8b,
			0x22, 0x6b, 0xef, 0x99, 0x65, 0xa7, 0x62, 0x27, 0x11, 0xcd,
			0x7d, 0xc2, 0xf5, 0x23, 0x3b, 0xb4, 0xb2, 0x85, 0xab, 0x01,
			0x97, 0x51, 0x8e, 0xd6, 0x78, 0x23, 0xeb, 0x9c, 0x93, 0x0a,
			0xb6, 0xa0, 0x7f, 0x25, 0x37, 0x33, 0xc6, 0x42, 0x0c, 0x73,
			0x8d, 0xec, 0x34, 0x20, 0xa1, 0x01, 0x6c, 0xda, 0xe2, 0x3c,
			0xe4, 0x2a, 0xd9, 0xaf, 0xa6, 0xd7, 0x6d, 0x70, 0x33, 0x93,
			0xfa, 0x74, 0x39, 0xab, 0xa1, 0x4f, 0xfb, 0x0c, 0xa1, 0x9e,
			0x67, 0x53, 0x77, 0x95, 0x60, 0xde, 0x01, 0x8b, 0xb0, 0x60,
			0x95, 0x6d, 0x87, 0xa2, 0xc3, 0xbe, 0xb6, 0xbe, 0x97, 0xe9,
			0x71, 0x33, 0x5f, 0x44, 0x20, 0x15, 0x06, 0x89, 0x54, 0x8d,
			0x72, 0x2e, 0x93, 0x3b, 0x57, 0xd5, 0x15, 0x21, 0x1a, 0x00,
			0xc4, 0x7b, 0xec, 0xa0, 0x75, 0xcf, 0x1d, 0x15, 0x1a, 0x18,
			0x9b, 0xd8, 0xb1, 0xd8, 0xbf, 0x59, 0x4b, 0xf4, 0xe3, 0x37,
			0x93, 0x3a, 0xbe, 0x1f, 0x45, 0x0b, 0xc1, 0x5f, 0xbd, 0x6a,
			0x72, 0x78, 0x9d, 0xb7, 0x5a, 0xd4, 0xa7, 0xa5, 0xd9, 0x83,
			0x3d, 0xda, 0x48, 0x49, 0x20, 0x87, 0xd8, 0x5a, 0xbf, 0x08,
			0x6d, 0xc8, 0xc9, 0x96, 0x54, 0xc1, 0xc9, 0xc2, 0x27, 0xbb,
			0xbe, 0x08, 0xae, 0x22, 0xdd, 0xb2, 0xb6, 0x56, 0xa0, 0x78,
			0xb4, 0xa1, 0xe8, 0x27, 0xd5, 0x5f, 0x3a, 0xb4, 0xd5, 0xdf,
			0xc3, 0x01, 0x5b, 0x79, 0xd6, 0xee, 0x82, 0x43, 0x32, 0xfc,
			0x57, 0x2d, 0xd2, 0x61, 0xb3, 0xcd, 0xe6, 0xe6, 0x12, 0xd5,
			0xa9, 0x74, 0x63, 0x45, 0xa6, 0xac, 0x34, 0x6e, 0x4f, 0x7f,
			0x67, 0x5a, 0xda, 0x47, 0xec, 0x69, 0x13, 0xff, 0x78, 0x2b,
			0xc6, 0x93, 0xe8, 0x49, 0x8f, 0x00, 0xa9, 0x49, 0xfb, 0x34,
			0x06, 0xbb, 0x30, 0x47, 0x1d, 0x81, 0xbc, 0x24 },
		{	0x86, 0x44, 0x65, 0x48, 0x98, 0x02, 0x89, 0x94, 0xe2, 0xba,
			0xcd, 0xbd, 0x38, 0x31, 0xa1, 0xed },
		},
	{ 24, 16, 20,
		{	0x48, 0xb8, 0x2b, 0x72, 0xfc, 0x81, 0xbe, 0x86,
			0x86, 0x0f, 0x72, 0x06, 0x5e, 0xfa, 0x62, 0x18,
			0x6f, 0x9d, 0xa5, 0x96, 0xbd, 0xf9, 0x51, 0x58 },
		{	0x24, 0xda, 0x67, 0xae, 0xf7, 0x4b, 0xe3, 0x33,
			0x85, 0x89, 0xcc, 0xb6 },
		{	0xf8, 0x6a, 0x57, 0xa3, 0x0c, 0x06, 0xef, 0xb1,
			0x0e, 0xcb, 0xeb, 0x3d, 0x5a, 0x9d, 0x97, 0xb5},
		{	0xc1, 0xf7, 0xf5, 0xc8, 0xf8, 0xcc, 0x51, 0x37,
			0xa5, 0x39, 0x91, 0x94, 0x1f, 0x38, 0x8f, 0xfd,
			0x2b, 0x27, 0xf0, 0xdd},
		{	0x4b, 0xe5, 0x8c, 0xd0, 0x63, 0x78, 0xc0, 0x38,
			0x78, 0xd4, 0xf1, 0x65, 0x94, 0x43, 0xc5, 0xd1},
		{	0x84, 0xdd, 0x00, 0xb8, 0xb0, 0x3a, 0xcb, 0x92,
			0x19, 0xec, 0x51, 0x16, 0xe3, 0xde, 0x73, 0x62}
		},
#endif /* !USE_LIBSODIUM_AES_GCM */
	{ 32, 32, 16,
		{	0x27, 0x2d, 0x16, 0x49, 0xa3, 0xdd, 0x80, 0x4d,
			0xe0, 0x96, 0x2d, 0x3e, 0x07, 0x06, 0x4a, 0x70,
			0x54, 0xc0, 0x0a, 0x62, 0x34, 0xab, 0x1b, 0x0c,
			0xdc, 0xf6, 0x85, 0xab, 0x39, 0x48, 0x37, 0xe5},
		{	0x95, 0x5b, 0x58, 0x97, 0xf6, 0xb9, 0x80, 0x6b,
			0xbe, 0xc5, 0xc3, 0x3e},
		{	0x36, 0xe5, 0x7c, 0x29, 0xc0, 0x8c, 0x51, 0xad,
			0x7f, 0xa9, 0x1c, 0x04, 0x16, 0xf9, 0x76, 0xcf,
			0xd0, 0x11, 0x78, 0x0e, 0xb4, 0x4c, 0xc5, 0xab,
			0xd3, 0x4c, 0x7b, 0x43, 0x1b, 0x09, 0x3b, 0x8d},
		{	0x33, 0xe6, 0x18, 0xec, 0xbb, 0xe5, 0xeb, 0x05,
			0x66, 0xdf, 0x21, 0xc3, 0xc3, 0x4b, 0x7e, 0x25},
		{	0xcd, 0x6a, 0xeb, 0x34, 0x50, 0x81, 0xdc, 0x0b,
			0xb2, 0xc8, 0xb4, 0xd1, 0x9b, 0x28, 0x06, 0x58,
			0xfb, 0x87, 0xc0, 0xf2, 0xbd, 0x0f, 0x4c, 0x9d,
			0xa6, 0x94, 0xdc, 0x1f, 0xee, 0xb3, 0x2f, 0x4e},
		{	0xdd, 0x37, 0xea, 0xc6, 0xbd, 0x6a, 0x4d, 0x36,
			0x18, 0x24, 0x17, 0x38, 0x77, 0x97, 0x35, 0xd7}
		}
	};
/*
	Test GCM mode AES
*/
	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
#ifndef USE_CL_GCM_GIV
		if (tests[i].keylen * 8 == 192)
			continue; /* Skip AES-192 as some impl do not support it. */
#endif /* USE_CL_GCM_GIV */
		if (i == 1) {
			_psTraceInt("	AES-GCM-%d long known vector encrypt test... ", tests[i].keylen * 8);
		} else {
			_psTraceInt("	AES-GCM-%d known vector encrypt test... ", tests[i].keylen * 8);
		}
		psAesInitGCM(&eCtx, tests[i].key, tests[i].keylen);
		psAesReadyGCM(&eCtx, tests[i].iv, tests[i].aad, tests[i].aadlen);
		psAesEncryptGCM(&eCtx, tests[i].pt, ciphertext, tests[i].ptlen);
		psAesGetGCMTag(&eCtx, 16, tag);
		if ((memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0) ||
				(memcmp(tag, tests[i].tag, 16) != 0)) {
			printf("FAILED: memcmp mismatch\n");
			res = PS_FAILURE;
		} else {
			printf("PASSED\n");
		}

#ifndef USE_ONLY_DECRYPT_GCM_WITH_TAG
		_psTraceInt("	AES-GCM-%d known vector decrypt (tagless) test... ", tests[i].keylen * 8);
		psAesInitGCM(&dCtx, tests[i].key, tests[i].keylen);
		psAesReadyGCM(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen);
#ifdef USE_LIBSODIUM_AES_GCM
		/* TODO - libsodium cipher text must include the tag */
		unsigned char * cipherTextAuthData;
		cipherTextAuthData = psMalloc(NULL, tests[i].ptlen+16);

		memcpy(cipherTextAuthData,tests[i].ct,tests[i].ptlen);
		memcpy(cipherTextAuthData+tests[i].ptlen,tests[i].tag,16);

		if (psAesDecryptGCM(&dCtx,cipherTextAuthData, tests[i].ptlen+16,plaintext,tests[i].ptlen) != PS_SUCCESS) {
			printf("FAILED: authentication failed\n");
		} else if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) {
			printf("FAILED: data mismatch\n");
		} else {
			printf("PASSED\n");
		}
		psFree(cipherTextAuthData, NULL);
#else
		psAesDecryptGCMtagless(&dCtx, tests[i].ct, plaintext, tests[i].ptlen);
		memset(tag, 0x0, 16);
		psAesGetGCMTag(&dCtx, 16, tag);
		if ((memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) ||
				(memcmp(tag, tests[i].tag, 16) != 0)) {
			printf("FAILED: memcmp mismatch\n");
			res = PS_FAILURE;
		} else {
			printf("PASSED\n");
		}
#endif
		psAesClearGCM(&dCtx);
		memset(tag, 0x0, 16);
		memset(plaintext, 0x0, 32);
#endif /* !defined USE_ONLY_DECRYPT_GCM_WITH_TAG */

		for(l = 0; l < (int32) sizeof(taglen); l++) {
			_psTraceInt(tagmsg[l], tests[i].keylen * 8);
			memset(plaintext, 0x11, sizeof(plaintext));
			memset(ciphertext_with_tag, 0x22, sizeof(ciphertext_with_tag));
			memcpy(ciphertext_with_tag, tests[i].ct, tests[i].ptlen);
			memcpy(ciphertext_with_tag + tests[i].ptlen, tests[i].tag, taglen[l]);
			psAesInitGCM(&dCtx, tests[i].key, tests[i].keylen);
			psAesReadyGCM(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen);
			if (psAesDecryptGCM(&dCtx, ciphertext_with_tag, tests[i].ptlen + taglen[l],
								plaintext, tests[i].ptlen) == PS_SUCCESS) {
				if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) {
					printf("FAILED: memcmp mismatch\n");
					res = PS_FAILURE;
				} else {
					printf("PASSED\n");
				}
			} else {
				printf("FAILED: tag verify failure\n");
				res = PS_FAILURE;
			}
		}
		for(l = 0; l < (int32) sizeof(taglen); l++) {
			_psTraceInt(tagmsg2[l], tests[i].keylen * 8);
			memset(plaintext, 0x11, sizeof(plaintext));
			memset(ciphertext_with_tag, 0x22, sizeof(ciphertext_with_tag));
			memcpy(ciphertext_with_tag, tests[i].ct, tests[i].ptlen);
			memcpy(ciphertext_with_tag + tests[i].ptlen, tests[i].tag, taglen[l]);
			ciphertext_with_tag[tests[i].ptlen + taglen[l] - 1]++;
			psAesInitGCM(&dCtx, tests[i].key, tests[i].keylen);
			psAesReadyGCM(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen);
			if (psAesDecryptGCM(&dCtx, ciphertext_with_tag, tests[i].ptlen + taglen[l],
								plaintext, tests[i].ptlen) != PS_SUCCESS) {
				printf("PASSED\n");
			} else {
				printf("FAILED: verify accepts invalid tag\n");
				res = PS_FAILURE;
			}
		}
	}
	return res;
}
#endif /* USE_AES_GCM */

#endif /* USE_AES */

#if 0
static psAesHmacPerf(void)
{
/*
	 Time AES-CBC encryption and decryption of AES_KB of data
 */
	useHmac = 0;
	aesTag = "AES-CBC";
L_CBC_TIMING:
#ifdef USE_AESNI_CRYPTO
	printf("Timing %s with %d KiB of data (aes-ni)\n", aesTag, AES_KB);
#else
	printf("Timing %s with %d KiB of data\n", aesTag, AES_KB);
#endif
	buf = psMalloc(pool, 1024 + 20);
	for (keysize = 16; keysize <= 32; keysize += 16) {
	_psTraceInt("AES-%d Key\n", keysize == 16 ? 128 : 256);
	for (i = 0; i < 1024; i++) {
		buf[i] = (unsigned char)(i & 0xFF);
	}
	memset(iv, 0x1, 16);
	memset(cbckey, 0x2, keysize);
	memset(plaintext, 0x3, 16);
	memset(hmackey, 0x4, 20);
	hmackeylen = 20;
	psAesInit(&encryptCtx, iv, cbckey, keysize);
	psGetTime(&start, NULL);
	for (k = 0; k < AES_KB; k++) {
		if (useHmac) psHmacSha1(hmackey, hmackeylen, buf, 1024, buf + 1024,
			hmackey, &hmackeylen);
		if (psAesEncrypt(&encryptCtx, buf, buf, 1024) != 1024) {
printf("ERROR LINE %d\n", __LINE__);
			return PS_FAILURE;
		}
	}
	psGetTime(&end, NULL);
	printf("%s: encrypt %u msecs\n", aesTag, psDiffMsecs(start, end, NULL));
	if (buf[0] == 0 && buf[1] == 1 && buf[2] == 2 && buf[3] == 3) {
		return PS_FAILURE;
	}
	psAesInit(&decryptCtx, iv, cbckey, keysize);
	psGetTime(&start, NULL);
	for (k = 0; k < AES_KB; k++) {
		if (useHmac) psHmacSha1(hmackey, hmackeylen, buf, 1024, buf + 1024,
			hmackey, &hmackeylen);
		if (psAesDecrypt(&decryptCtx, buf, buf, 1024) != 1024) {
			return PS_FAILURE;
		}
	}
	psGetTime(&end, NULL);
	printf("%s: decrypt %u msecs\n", aesTag, psDiffMsecs(start, end, NULL));
	}
	psFree(buf, pool);
	if (useHmac == 0) {
		useHmac = 1;
		aesTag = "AES-CBC-SHA-HMAC";
		goto L_CBC_TIMING;
	}

	return PS_SUCCESS;
}
#endif /* 0 */

#ifdef USE_CHACHA20_POLY1305
#define TEST_TEXT_MAXLEN 128
#define TEST_AAD_MAXLEN 32
#ifdef USE_LIBSODIUM_CHACHA20_POLY1305
 #define TEST_TAG_LEN crypto_aead_chacha20poly1305_ABYTES
 #define TEST_KEY_LEN crypto_aead_chacha20poly1305_KEYBYTES
 #ifdef CHACHA20POLY1305_IETF
  #define TEST_IV_LEN crypto_aead_chacha20poly1305_IETF_NPUBBYTES
 #else
  #define TEST_IV_LEN crypto_aead_chacha20poly1305_NPUBBYTES
 #endif
#else
 #define TEST_TAG_LEN 16
 #define TEST_KEY_LEN 32
 #define TEST_IV_LEN 12
#endif

int32 psChacha20Poly1305Test(void)
{
	int32				i;
	psChacha20Poly1305_t	eCtx, dCtx;
	unsigned char		ciphertext[TEST_TEXT_MAXLEN];
	unsigned char		plaintext[TEST_TEXT_MAXLEN];
	unsigned char		tag[TEST_TAG_LEN];

	static struct {
		int32 keylen, ptlen, aadlen;
		unsigned char key[TEST_KEY_LEN], iv[TEST_IV_LEN], pt[TEST_TEXT_MAXLEN], aad[TEST_AAD_MAXLEN], ct[TEST_TEXT_MAXLEN], tag[TEST_TAG_LEN];
	} tests[] = {

#ifdef CHACHA20POLY1305_IETF
		{ TEST_KEY_LEN, 114, 12,
		{	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
		0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
		0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f},
		// IV
		{	0x07, 0x00, 0x00, 0x00,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 },
		// pt
		{	0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,
		0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c,
		0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,
		0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73,
		0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,
		0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63,
		0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,
		0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f,
		0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,
		0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20,
		0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,
		0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73,
		0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,
		0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69,
		0x74,0x2e},
		// aad
		{	0x50, 0x51, 0x52, 0x53, 
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7},
		// ct
		{	0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb,
		0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2,
		0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe,
		0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6,
		0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12,
		0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b,
		0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29,
		0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36,
		0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c,
		0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58,
		0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94,
		0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc,
		0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d,
		0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b,
		0x61,0x16},
		// tag
		{	0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a,
		0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91}
		},

		{ TEST_KEY_LEN, 114, 0,
		{	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
		0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
		0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f},
		// IV
		{	0x07, 0x00, 0x00, 0x00,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 },
		// pt
		{	0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,
		0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c,
		0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,
		0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73,
		0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,
		0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63,
		0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,
		0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f,
		0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,
		0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20,
		0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,
		0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73,
		0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,
		0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69,
		0x74,0x2e},
		// aad
		{""},
		// ct
		{	0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb,
		0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2,
		0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe,
		0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6,
		0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12,
		0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b,
		0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29,
		0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36,
		0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c,
		0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58,
		0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94,
		0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc,
		0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d,
		0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b,
		0x61,0x16},
		// tag
		{	0x6a,0x23,0xa4,0x68,0x1f,0xd5,0x94,0x56,
		0xae,0xa1,0xd2,0x9f,0x82,0x47,0x72,0x16}
		}
#else
		{ TEST_KEY_LEN, 16, 13,
		{ 0x70, 0xd5, 0xbd, 0x03, 0xc6, 0x17, 0x68, 0xb2, 
		  0xd5, 0xce, 0xb4, 0xa4, 0x15, 0xc6, 0xf8, 0x40,
		  0xf5, 0xd4, 0xbf, 0x5e, 0x63, 0x2b, 0xb6, 0xf3,
		  0x73, 0xaf, 0xcd, 0xd7, 0xbb, 0xba, 0x85, 0xa7 },
		// Nonce
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		// pt
		{ 0x14, 0x00, 0x00, 0x0c, 
		  0x9c, 0x49, 0x65, 0xfc, 0xeb, 0x2e, 0xfa, 0x01, 0xfc, 0xa1, 0x2a, 0xaf },
		// aad
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		  0x16, 0x03, 0x03, 0x00, 0x10 },
		// ct
		{ 0x25, 0xd8, 0x3d, 0x53, 0xbd, 0x03, 0xdd, 0x69, 
		  0x5a, 0x44, 0x6f, 0xde, 0x0c, 0x3d, 0x87, 0x93},
		// tag
		{ 0x80, 0x53, 0x32, 0x2f, 0x5c, 0x27, 0x8f, 0x9d,
		  0x78, 0xb5, 0x25, 0x3d, 0x5c, 0xc3, 0x8c, 0x9b }
		}
#endif
	};

/* Test AEAD CHACHA20-POLY1305 */

	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTraceInt("	CHACHA20-POLY1305-%d "
#ifdef CHACHA20POLY1305_IETF
		"IETF "
#endif
		"known vector encrypt test... ", tests[i].keylen * 8);

		psChacha20Poly1305Init(&eCtx, tests[i].key, tests[i].keylen);
		psChacha20Poly1305Ready(&eCtx, tests[i].iv, tests[i].aad, tests[i].aadlen);
		psChacha20Poly1305Encrypt(&eCtx, tests[i].pt, ciphertext, tests[i].ptlen);
		psChacha20Poly1305GetTag(&eCtx, TEST_TAG_LEN, tag);

		if ((memcmp(ciphertext, tests[i].ct, tests[i].ptlen) != 0) ||
				(memcmp(tag, tests[i].tag, TEST_TAG_LEN) != 0)) {
			printf("FAILED: memcmp mismatch\n");
		} else {
			printf("PASSED\n");
		}
		psChacha20Poly1305Clear(&eCtx);
		memset(tag, 0x0, TEST_TAG_LEN);
		memset(ciphertext, 0x0, TEST_TEXT_MAXLEN);

		_psTraceInt("	CHACHA20-POLY1305-%d "
#ifdef CHACHA20POLY1305_IETF
		"IETF "
#endif
		"known vector decrypt test... ", tests[i].keylen * 8);
		psChacha20Poly1305Init(&dCtx, tests[i].key, tests[i].keylen);
		psChacha20Poly1305Ready(&dCtx, tests[i].iv, tests[i].aad, tests[i].aadlen);

		// Cipher text must include the tag
		unsigned char * cipherTextAuthData;
		cipherTextAuthData = psMalloc(NULL, tests[i].ptlen+TEST_TAG_LEN);

		memcpy(cipherTextAuthData,tests[i].ct,tests[i].ptlen);
		memcpy(cipherTextAuthData+tests[i].ptlen,tests[i].tag,TEST_TAG_LEN);

		if (psChacha20Poly1305Decrypt(&dCtx,cipherTextAuthData,
				tests[i].ptlen+TEST_TAG_LEN,plaintext,tests[i].ptlen) < 0) {
			printf("FAILED: authentication failed\n");
		} else if (memcmp(plaintext, tests[i].pt, tests[i].ptlen) != 0) {
			printf("FAILED: data mismatch\n");
		} else {
			printf("PASSED\n");
		}
		psFree(cipherTextAuthData, NULL);
		psChacha20Poly1305Clear(&dCtx);
		memset(tag, 0x0, TEST_TAG_LEN);
		memset(plaintext, 0x0, TEST_TEXT_MAXLEN);
	}
	return PS_SUCCESS;
}
#endif /* USE_CHACHA20_POLY1305 */

/******************************************************************************/
#ifdef USE_DES
#define DES_ITER	1000
static int32 psDesTest(void)
{
	int32 err;
	static const struct des_test_case {
		int32 num, mode; /* mode 1 = encrypt */
		unsigned char key[8], txt[8], out[8];
	} cases[] = {
		{ 1, 1,     { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
					{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } },
		{ 2, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 },
					{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 3, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 },
					{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 4, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA },
					{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 5, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F },
					{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 6, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 },
					{ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 7, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF },
					{ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 8, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F },
					{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 9, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 },
					{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{10, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A },
					{ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },

		{ 1, 0,     { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
					{ 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 },
					{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
		{ 2, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } },
		{ 3, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } },
		{ 4, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } },
		{ 5, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } },
		{ 6, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } },
		{ 7, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } },
		{ 8, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } },
		{ 9, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } },
		{10, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
					{ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					{ 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } }

	};

	int32 i, y;
	unsigned char tmp[8];
	psDes3Key_t des;

	for(i=0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++)
	{
		if ((err = psDesInitKey(cases[i].key, 8, &des)) != PS_SUCCESS) {
		   return err;
		}
		if (cases[i].mode != 0) {
			_psTraceInt("	DES known vector encrypt test %d... ", cases[i].num);
		   psDesEncryptBlock(cases[i].txt, tmp, &des);
		} else {
			_psTraceInt("	DES known vector encrypt test %d... ", cases[i].num);
		   psDesDecryptBlock(cases[i].txt, tmp, &des);
		}

		if (memcmp(cases[i].out, tmp, sizeof(tmp)) != 0) {
			_psTrace("FAILED:  memcmp\n");
		   return -1;
		} else {
			_psTrace("PASSED\n");
		}

	  /* now see if we can encrypt all zero bytes DES_ITER times,
	   decrypt and come back where we started */
		_psTrace("	DES wind/unwind test... ");
		for (y = 0; y < 8; y++) tmp[y] = 0;
		for (y = 0; y < DES_ITER; y++) psDesEncryptBlock(tmp, tmp, &des);
		for (y = 0; y < DES_ITER; y++) psDesDecryptBlock(tmp, tmp, &des);
		for (y = 0; y < 8; y++) {
			if (tmp[y] != 0) {
				_psTrace("FAILED:  memcmp\n");
				return -1;
			}
		}
		_psTrace("PASSED\n");
	}

	return PS_SUCCESS;
}
#endif /* DES */

#ifdef USE_PKCS5
int32 psPBKDF2(void)
{
	int32	i;
	unsigned char	key[32];
	static struct {
		int32 rounds, dkLen;
		unsigned char *pass, *salt;
		unsigned char output[32];
	} tests[] = {
	{ 1, 20, (unsigned char *)"password", (unsigned char *)"salt",
		{ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5,
			0x24, 0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6}
		},
	{ 4096, 20, (unsigned char *)"password", (unsigned char *)"salt",
		{ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49,
			0xd9, 0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1}
		},
	{ 4096, 25, (unsigned char *)"passwordPASSWORDpassword",
		(unsigned char *)"saltSALTsaltSALTsaltSALTsaltSALTsalt",
		{ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8,
			0x36, 0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2,
			0xf0, 0x70, 0x38}
		}
	};

	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTraceInt("	PBKDF2 known vector test %d... ", i + 1);
		pkcs5pbkdf2(tests[i].pass, (uint32)strlen((char*)tests[i].pass),
			tests[i].salt, (uint32)strlen((char*)tests[i].salt),
			tests[i].rounds, key, tests[i].dkLen);
		if (memcmp(key, tests[i].output, tests[i].dkLen) != 0) {
			_psTrace("FAILED\n");
		} else {
			_psTrace("PASSED\n");
		}
	}
	return 0;
}
#endif /* PKCS5 */

/******************************************************************************/
#ifdef USE_3DES
int32 psDes3Test(void)
{
	static struct {
		unsigned char key[24], iv[8], pt[8], ct[8];
	} tests[] = {
	{
		{ 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		{ 0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d }
		},

	{
		{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		{ 0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00 },
		{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
		},
	{
		{ 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
			0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
			0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31},
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		{ 0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4 }
		}
	};
	psDes3_t			skey;
	unsigned char		ct[32];
	int32				i;

	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTraceInt("	3DES CBC known vector test %d... ", i + 1);
		if (psDes3Init(&skey, tests[i].iv, tests[i].key) < 0) {
			return PS_FAILURE;
		}
		psDes3Encrypt(&skey, tests[i].pt, ct, DES3_BLOCKLEN);
		if (memcmp(ct, tests[i].ct, DES3_BLOCKLEN) != 0) {
			_psTrace("FAILED\n");
		} else {
			_psTrace("PASSED\n");
		}
		psDes3Clear(&skey);
	}
	return 0;
}
#endif /* USE_3DES */
/******************************************************************************/

#ifdef USE_ARC4
int32 psArc4Test(void)
{
	static struct {
		int32	keylen, ptlen;
		unsigned char key[24], pt[16], ct[16];
	} tests[] = {
	{ 5, 16,
		{ 0x01, 0x02, 0x03, 0x04, 0x05 },
		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
		{ 0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27,
			0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11, 0x18, 0xa8 }
		},
	{ 8, 8,
		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
		{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
		{ 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }
		}
	};
	psArc4_t			skey;
	unsigned char		ct[32];
	int32				i;

	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTraceInt("	RC4 known vector test %d... ", i + 1);
		if (psArc4Init(&skey, tests[i].key, tests[i].keylen) < 0) {
			return PS_FAILURE;
		}
		psArc4(&skey, tests[i].pt, ct, tests[i].ptlen);
		if (memcmp(ct, tests[i].ct, tests[i].ptlen) != 0) {
			_psTrace("FAILED\n");
		} else {
			_psTrace("PASSED\n");
		}
		psArc4Clear(&skey);
	}
	return 0;
}
#endif /* USE_ARC4 */

#ifdef USE_IDEA
int32 psIdeaTest(void)
{
	int32	err, i;
	psIdea_t	eCtx, dCtx;
	unsigned char tmp[2][IDEA_BLOCKLEN];

	static struct {
		unsigned char key[IDEA_KEYLEN], iv[IDEA_IVLEN], pt[16], ct[16];
	} tests[] = {
	{
		{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7,
			0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
		{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
		{ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
			0x64, 0x21, 0x21, 0x21, 0x21, 0x0a },
		{ 0x57, 0x1c, 0xce, 0x5a, 0xea, 0xee, 0x81, 0x04, 0x87, 0x2a,
			0x5a, 0xa9, 0xe2, 0xdf, 0x64, 0xa9 }
		}
	};


	for (i = 0; i < (int32)(sizeof(tests)/sizeof(tests[0])); i++) {
		_psTrace("	IDEA-CBC known vector test 1... ");
		if ((err = psIdeaInit(&eCtx, tests[i].iv, tests[i].key))
				!=	PS_SUCCESS) {
			_psTraceInt("FAILED:  psIdeaInit returned %d\n", err);
			return err;
		}
		if ((err = psIdeaInit(&dCtx, tests[i].iv, tests[i].key))
				!=	PS_SUCCESS) {
			_psTraceInt("FAILED:  psIdeaInit returned %d\n", err);
			return err;
		}
		psIdeaEncrypt(&eCtx, tests[i].pt, tmp[0], 16);
		//psTraceBytes("IDEA CT", tmp[0], 16);
		if (memcmp(tmp[0], tests[i].ct, 16) != 0) {
			_psTrace("FAILED\n");
		} else {
			_psTrace("PASSED\n");
		}
		_psTrace("	IDEA-CBC known vector test 2... ");
		psIdeaDecrypt(&dCtx, tmp[0], tmp[1], 16);
		//psTraceBytes("IDEA PT", tmp[1], 16);
		if (memcmp(tmp[1], tests[i].pt, 16) != 0) {
			_psTrace("FAILED\n");
		} else {
			_psTrace("PASSED\n");
		}

		psIdeaClear(&eCtx);
		psIdeaClear(&dCtx);
	}
	return 0;
}
#endif

/******************************************************************************/
#ifdef USE_SEED
/*
  Performs a self-test of the SEED block cipher
  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
*/
int32 psSeedTest(void)
{
#if 0
	static const struct test {
		unsigned char pt[16], ct[16], key[16];
	} tests[] = {
		{
			{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F },
			{ 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB },
			{ 0 },
		},

		{
			{ 0 },
			{ 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 },
			{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F },
		},

		{
			{ 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D },
			{ 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A },
			{ 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 },
		},

		{
			{ 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 },
			{ 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 },
			{ 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 },
		}
	};

	int32			x;
	unsigned char	buf[2][16];
	psSeedKey_t		skey;

	for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
		psSeedInitKey(tests[x].key, 16, &skey);
		psSeedEncryptBlock(tests[x].pt, buf[0], &skey);
		psSeedDecryptBlock(buf[0], buf[1], &skey);
		if (memcmp(buf[0], tests[x].ct, 16) || memcmp(buf[1], tests[x].pt, 16)){
			_psTraceInt("SEED failure: test %d failed\n", x);
			return -1;
		}
		psSeedClear(&skey);
	}
#endif
	_psTrace("	SEED unimplemented\n");

	return PS_SUCCESS;
}
#endif /* USE_SEED */
/******************************************************************************/

/******************************************************************************/
#ifdef USE_SHA1
int32  psSha1Test(void)
{
	static const struct {
		char *msg;
		unsigned char hash[SHA1_HASHLEN];
	} tests[] = {
		{ "abc",
		{ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
			0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
			0x9c, 0xd0, 0xd8, 0x9d }
		},
		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
		{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
			0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
			0xE5, 0x46, 0x70, 0xF1 }
		},
		{ "The quick brown fox jumps over the lazy dog",
		{ 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e,
			0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12 }
		},
		{ "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefefaeofadflafefaefeaeorea",
		{ 0xb5, 0x6a, 0x92, 0x83, 0x2a, 0xb8, 0x98, 0xdf, 0x37, 0xf6, 0x4b,
			0x5b, 0x95, 0x9b, 0xfe, 0x9a, 0xb5, 0x9f, 0x36, 0x86}
		}
	};

	int32 i;
	unsigned char tmp[SHA1_HASHLEN];
	psSha1_t	md;

	for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0]));  i++) {
		_psTraceInt("	SHA-1 known vector test %d... ", i + 1);
		psSha1Init(&md);
		psSha1Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg));
		psSha1Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, SHA1_HASHLEN) != 0) {
			_psTrace("FAILED: mem compare failure\n");
			return -1;
		} else {
			_psTrace("PASSED\n");
		}
	}
	return PS_SUCCESS;
}

#endif /* USE_SHA1 */
/******************************************************************************/

/******************************************************************************/
#ifdef USE_SHA256
int32 psSha256Test2(void)
{
	unsigned char hash[32];
	const unsigned char expect[32] = {
		0x1, 0xd, 0x0, 0xed, 0xa0, 0x5, 0xa3, 0x8c, 0xcb, 0x98, 0xc3,
		0x9b, 0x2d, 0xb1, 0x43, 0x2d, 0x59, 0x9, 0x8, 0x37, 0x40, 0x31,
		0x5e, 0x9b, 0x27, 0xec, 0x92, 0xf7, 0x2, 0xa7, 0x1c, 0x18 };
	const unsigned char expect2[32] = {
		0x5a, 0x31, 0xd2, 0xdf, 0x29, 0x5c, 0x83, 0x76, 0x92, 0x64, 0xae,
		0x53, 0xcd, 0xc8, 0xeb, 0x56, 0xfc, 0x55, 0x3, 0x6, 0x92, 0xe, 0x8b,
		0xab, 0x18, 0x7b, 0x47, 0xd1, 0xa2, 0x96, 0x31, 0xe };
	const unsigned char expect3[32] = {
		0xff, 0x16, 0x42, 0xc4, 0x77, 0x1, 0x1d, 0x25, 0xd, 0x48, 0xe4, 0x2d,
		0xba, 0xab, 0x4f, 0x14, 0x1e, 0xd5, 0x7f, 0xd6, 0x60, 0x9e, 0x51,
		0x91, 0xab, 0x4, 0xf9, 0xf6, 0xf6, 0x5d, 0x8f, 0x22 };
	unsigned char array[65536];
	unsigned char array2[65536];
	unsigned char array3[65536];
	psSha256_t md;
	psSha256_t md2;
	psSha256_t md3;
	psSha256_t md4;
	int i;
	int blocksize;
	int blocksize2;
	int blocksize3;

	/* This test assumes there is 1 or 2 simultanous digest contexts in
	   underlying implementation of cryptography, as is the case with some
	   non-default crypto implementations. The test works with more than that,
	   but may not check of the implementation. */

	/* Additional tests, using multiple simultaneous contexts, and
	   large data. */

	/* First perform hashes with single blocks and serially. */
	for(i = 0; i < sizeof(array); i++)
	{
		array[i] = 7 + (i * 2048) % 127;
		array2[i] = 17 + (i * 4096) % 197;
		array3[i] = 21 + (i * 8192) % 227;
	}

	memset(hash, 0, sizeof(hash));
	psSha256Init(&md);
	psSha256Update(&md, array, 65536);
	psSha256Final(&md, hash);

	if (memcmp(hash, expect, 32) != 0) {
		abort();
		_psTrace("FAILED: memcmp\n");
		return -1;
	}

	memset(hash, 0, sizeof(hash));
	psSha256Init(&md2);
	psSha256Update(&md2, array2, 65536);
	psSha256Final(&md2, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		abort();
		_psTrace("FAILED: memcmp\n");
		return -1;
	}

	memset(hash, 0, sizeof(hash));
	psSha256Init(&md3);
	psSha256Update(&md3, array3, 65536);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		abort();
		_psTrace("FAILED: memcmp\n");
		return -1;
	}

	/* Then perform hashes with two blocks and serially, using same context. */
	memset(hash, 0, sizeof(hash));
	psSha256Init(&md);
	psSha256Update(&md, array, 32768);
	psSha256Update(&md, array + 32768, 32768);
	psSha256Final(&md, hash);

	if (memcmp(hash, expect, 32) != 0) {
		_psTrace("FAILED: memcmp (two part)\n");
		return -1;
	}

	memset(hash, 0, sizeof(hash));
	psSha256Init(&md);
	psSha256Update(&md, array2, 32768);
	psSha256Update(&md, array2 + 32768, 32768);
	psSha256Final(&md, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (two part)\n");
		return -1;
	}

	memset(hash, 0, sizeof(hash));
	psSha256Init(&md);
	psSha256Update(&md, array3, 32768);
	psSha256Update(&md, array3 + 32768, 32768);
	psSha256Final(&md, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		_psTrace("FAILED: memcmp (two part)\n");
		return -1;
	}

	/* Try going back within the same context: First initialize and update
	   and then initialize and update again. */

	memset(hash, 0, sizeof(hash));
	psSha256Init(&md);
	psSha256Update(&md, array, 32768);
	psSha256Init(&md);
	psSha256Update(&md, array3, 32768);
	psSha256Update(&md, array3 + 32768, 32768);
	psSha256Final(&md, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		_psTrace("FAILED: memcmp (two part)\n");
		return -1;
	}

	/* Do operations in parallel with three md contexts, single block. */
	psSha256Init(&md);
	psSha256Init(&md2);
	psSha256Init(&md3);
	psSha256Update(&md, array, 65536);
	psSha256Update(&md2, array2, 65536);
	psSha256Update(&md3, array3, 65536);

	psSha256Final(&md, hash);

	if (memcmp(hash, expect, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	psSha256Final(&md2, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	psSha256Final(&md3, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	/* Do operations in parallel with three md contexts, multiple blocks. */
	blocksize = 256;

	psSha256Init(&md);
	psSha256Init(&md2);
	psSha256Init(&md3);

	for(i = 0; i < 65536; i += blocksize) {
		psSha256Update(&md, &array[i], blocksize);
		psSha256Update(&md2, &array2[i], blocksize);
		psSha256Update(&md3, &array3[i], blocksize);
	}

	psSha256Final(&md, hash);

	if (memcmp(hash, expect, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	psSha256Final(&md2, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	psSha256Final(&md3, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	/* Do operations in parallel with three md contexts, multiple blocks.
	   Different block sizes for different md contexts. */
	blocksize = 256;
	blocksize2 = 512;
	blocksize3 = 2048;

	psSha256Init(&md);
	psSha256Init(&md2);
	psSha256Init(&md3);

	for(i = 0; i < 65536; i += blocksize) {
		psSha256Update(&md, &array[i], blocksize);
		if ((i % blocksize2) != 0)
			continue;
		psSha256Update(&md2, &array2[i], blocksize2);
		if ((i % blocksize3) != 0)
			continue;
		psSha256Update(&md3, &array3[i], blocksize3);
	}

	psSha256Final(&md, hash);

	if (memcmp(hash, expect, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	psSha256Final(&md2, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	psSha256Final(&md3, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	/* Multipart with context transfer (using memory copy). */
	psSha256Init(&md);
	psSha256Update(&md, array3, 32768);
	psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to
							 copy, zeroize or free md memory. */
	memcpy(&md3, &md, sizeof(md3));
	psSha256Update(&md3, array3 + 32768, 32768);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect3, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	/* Multipart with context transfer (using state copying). */
	psSha256Init(&md);
	psSha256Update(&md, array2, 32768);
	psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to
							 copy, zeroize or free md memory. */
	memcpy(&md3, &md, sizeof(md3));
	psSha256Update(&md3, array2 + 32768, 32768);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	/* Multipart with context transfer (using state copying and memcpy). */
	psSha256Init(&md);
	psSha256Update(&md, array2, 32768);
	psSha256Cpy(&md3, &md);
	psSha256Sync(&md3, 0);
	psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to
						  copy, zeroize or free md memory. */
	memcpy(&md3, &md, sizeof(md3));
	psSha256Update(&md3, array2 + 32768, 32768);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (single part; parallel contexts)\n");
		return -1;
	}

	/* Multipart with context transfer (using state copying), when
	   state is likely not loaded (variants with different amount of
	   activity in between Update and Cpy. */
	psSha256Init(&md);
	psSha256Update(&md, array2, 32768);

	psSha256Init(&md2);
	psSha256Update(&md2, array, 32768);
	psSha256Update(&md2, array, 32768);
	psSha256Final(&md2, hash);

	psSha256Cpy(&md3, &md);
	psSha256Update(&md3, array2 + 32768, 32768);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (multi part; parallel contexts)\n");
		return -1;
	}
	psSha256Init(&md);
	psSha256Update(&md, array2, 32768);

	psSha256Init(&md2);
	psSha256Update(&md2, array, 32768);
	psSha256Update(&md2, array, 32768);
	psSha256Init(&md3);
	psSha256Update(&md3, array, 32768);
	psSha256Update(&md3, array, 32768);
	psSha256Final(&md2, hash);
	psSha256Final(&md3, hash);

	psSha256Cpy(&md3, &md);
	psSha256Update(&md3, array2 + 32768, 32768);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (multi part; parallel contexts)\n");
		return -1;
	}
	psSha256Init(&md);
	psSha256Update(&md, array2, 32768);

	psSha256Init(&md2);
	psSha256Update(&md2, array, 32768);
	psSha256Update(&md2, array, 32768);
	psSha256Init(&md3);
	psSha256Update(&md3, array, 32768);
	psSha256Update(&md3, array, 32768);
	psSha256Init(&md4);
	psSha256Update(&md4, array, 32768);
	psSha256Update(&md4, array, 32768);
	psSha256Final(&md2, hash);
	psSha256Final(&md3, hash);
	psSha256Final(&md4, hash);

	psSha256Cpy(&md3, &md);
	psSha256Update(&md3, array2 + 32768, 32768);
	psSha256Final(&md3, hash);

	if (memcmp(hash, expect2, 32) != 0) {
		_psTrace("FAILED: memcmp (multi part; parallel contexts)\n");
		return -1;
	}

	/* Zeroize of context. */
	psSha256Init(&md);
	psSha256Update(&md, array, 32768);
	psSha256Sync(&md, 0); /* Need to synchronize before it is allowed to
							 copy, zeroize or free md memory. */
	memset(&md, 0, sizeof(md));

	/* Note: After memset it is needed to use some other contexts. */
	psSha256Init(&md2);
	psSha256Update(&md2, array, 32768);
	psSha256Update(&md2, array, 32768);
	psSha256Init(&md3);
	psSha256Update(&md3, array, 32768);
	psSha256Update(&md3, array, 32768);
	psSha256Init(&md4);
	psSha256Update(&md4, array, 32768);
	psSha256Update(&md4, array, 32768);

	psSha256Init(&md);
	psSha256Update(&md, array, 65536);
	psSha256Final(&md, hash);

	if (memcmp(hash, expect, 32) != 0) {
		_psTrace("FAILED: memcmp (memset in between)\n");
		return -1;
	}

	psSha256Final(&md2, hash);
	psSha256Final(&md3, hash);
	psSha256Final(&md4, hash);

	/* Sync is ok for zeroized memory not used as context and initialized
	   or finalized context. */
	memset(&md, 0, sizeof(md));
	psSha256Sync(&md, 0);
	memset(&md, 0, sizeof(md));
	psSha256Init(&md);
	psSha256Sync(&md, 0);
	psSha256Init(&md);
	psSha256Update(&md, array, 65536);
	psSha256Final(&md, hash);
	psSha256Sync(&md, 0);

	if (memcmp(hash, expect, 32) != 0) {
		_psTrace("FAILED: memcmp\n");
		return -1;
	}

	return PS_SUCCESS;
}

int32 psSha256Test(void)
{
	static const struct {
		char *msg;
		char *moreMsg;
		unsigned char hash[SHA256_HASHLEN];
	} tests[] = {
		{ "abc", NULL,
		{ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
			0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
			0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
			0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
		},
		{ "ab", "c",
		{ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
			0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
			0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
			0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
		},
		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", NULL,
		{ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
			0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
			0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
			0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
		},
		{ "abcdbcdecd", "efdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
		{ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
			0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
			0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
			0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
		},
		{ "The quick brown fox jumps over the lazy dog", NULL,
		{ 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
			0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
			0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c,	0xdb, 0x76,
			0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92 }
		},
		{ "The quick brow", "n fox jumps over the lazy dog",
		{ 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
			0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
			0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c,	0xdb, 0x76,
			0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92 }
		},
		{ "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefefaeofadflafefaefeaeorea", NULL,
		{ 0xd9, 0xe0, 0xb1, 0xfb, 0x08, 0x8a, 0xe4, 0xb9,
			0xfe, 0xf0, 0xb2, 0xb8, 0x33, 0x9e, 0x0f, 0xea,
			0x59, 0xa7, 0x35, 0x7f, 0x5b, 0x65, 0xde, 0x42,
			0x7b, 0xaa, 0x28, 0x89, 0xfd, 0x5f, 0x49, 0xd0}
		},
		{ "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefef", "aeofadflafefaefeaeorea",
		{ 0xd9, 0xe0, 0xb1, 0xfb, 0x08, 0x8a, 0xe4, 0xb9,
			0xfe, 0xf0, 0xb2, 0xb8, 0x33, 0x9e, 0x0f, 0xea,
			0x59, 0xa7, 0x35, 0x7f, 0x5b, 0x65, 0xde, 0x42,
			0x7b, 0xaa, 0x28, 0x89, 0xfd, 0x5f, 0x49, 0xd0}
		}
	};

	int32 i;
	unsigned char tmp[SHA256_HASHLEN];
	psSha256_t md;

	for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) {
		_psTraceInt("	SHA-256 known vector test %d... ", i + 1);
		psSha256Init(&md);
		psSha256Update(&md, (unsigned char*)tests[i].msg,
			(uint32)strlen(tests[i].msg));
		if (tests[i].moreMsg != NULL) {
			psSha256Update(&md, (unsigned char*)tests[i].moreMsg,
				(uint32)strlen(tests[i].moreMsg));
		}
		psSha256Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, SHA256_HASHLEN) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		} else {
			_psTrace("PASSED\n");
		}
	}

	_psTrace("	SHA-256 robustness test... ");
	if (psSha256Test2() == PS_SUCCESS) {
		_psTrace("PASSED\n");
	} else {
		return -1;
	}

	return PS_SUCCESS;
}
#endif /* USE_SHA256 */
/******************************************************************************/

#ifdef USE_SHA224
/**
  Self-test the hash
  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
int32 psSha224Test(void)
{
	static const struct {
		char *msg;
		unsigned char hash[28];
	} tests[] = {
		{ "abc",
			{ 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8,
			0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2,
			0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd,
			0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 }
		},
		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
			{ 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76,
			0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89,
			0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4,
			0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 }
		},
	};

	int i;
	unsigned char tmp[28];
	psDigestContext_t md;

	for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
		_psTraceInt("	SHA-224 known vector test %d... ", i + 1);
		psSha224Init(&md);
		psSha224Update(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
		psSha224Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, 28) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		} else {
			_psTrace("PASSED\n");
		}
	}
	return PS_SUCCESS;
}
#endif /* USE_SHA224 */

/******************************************************************************/

#ifdef USE_SHA512
int32 psSha512Test(void)
{
	static const struct {
		char *msg;
		unsigned char hash[SHA512_HASHLEN];
	} tests[] = {
		{ "abc",
		{ 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
		0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
		0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
		0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
		0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
		0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
		0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
		0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
		},
		{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
		{ 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
		0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
		0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
		0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
		0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
		0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
		0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
		0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
		},
	};

	int i;
	unsigned char tmp[SHA512_HASHLEN];
	psSha512_t	md;

	for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
		_psTraceInt("	SHA-512 known vector test %d... ", i + 1);
		psSha512Init(&md);
		psSha512Update(&md, (unsigned char *)tests[i].msg, (uint32)strlen(tests[i].msg));
		psSha512Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, SHA512_HASHLEN) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		}
		_psTrace("PASSED\n");
	}
	return PS_SUCCESS;
}
#endif /* USE_SHA512 */

#ifdef USE_SHA384
int32 psSha384Test(void)
{
	static const struct {
		char *msg;
		unsigned char hash[SHA384_HASHLEN];
	} tests[] = {
	{ "abc",
	  { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
		0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
		0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
		0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
		0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
		0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }
	},
	{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
	  { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
		0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
		0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
		0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
		0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
		0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 }
	},
	};

	int i;
	unsigned char tmp[SHA384_HASHLEN];
	psSha384_t md;

	for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
		_psTraceInt("	SHA-384 known vector test %d... ", i + 1);
		psSha384Init(&md);
		psSha384Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg));
		psSha384Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, SHA384_HASHLEN) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		}
		_psTrace("PASSED\n");
	}
	return PS_SUCCESS;
}
#endif /* USE_SHA384 */


#ifdef USE_MD5SHA1
int32  psMd5Sha1Test(void)
{
	static const struct {
		char *msg;
		unsigned char hash[36];
	} tests[] = {
		{ "abc",
		{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
			0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72,
			0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
			0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
			0x9c, 0xd0, 0xd8, 0x9d }
		},
		{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
		{ 0x82, 0x15, 0xef, 0x07, 0x96, 0xa2, 0x0b, 0xca,
			0xaa, 0xe1, 0x16, 0xd3, 0x87, 0x6c, 0x66, 0x4a,
			0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
			0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
			0xE5, 0x46, 0x70, 0xF1 }
		},
		{ "The quick brown fox jumps over the lazy dog",
		{ 0x9e, 0x10, 0x7d, 0x9d, 0x37, 0x2b, 0xb6, 0x82,
			0x6b, 0xd8, 0x1d, 0x35, 0x42, 0xa4, 0x19, 0xd6,
			0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc,
			0xed, 0x84, 0x9e, 0xe1, 0xbb, 0x76, 0xe7, 0x39,
			0x1b, 0x93, 0xeb, 0x12 }
		},
		{ "adfkadsofijadlkjoaijeoadaoijealfkajeflakepoieuproeirupqoeiruadslfasdlfadfowifjadfaleifafoeafwdflaheadfalefaahfaefefaeofadflafefaefeaeorea",
		{ 0x1b, 0x92, 0x8a, 0x64, 0x43, 0xfd, 0xdf, 0xa2,
			0x17, 0x05, 0x3b, 0x25, 0x08, 0x20, 0x81, 0xe5,
			0xb5, 0x6a, 0x92, 0x83, 0x2a, 0xb8, 0x98, 0xdf,
			0x37, 0xf6, 0x4b, 0x5b, 0x95, 0x9b, 0xfe, 0x9a,
			0xb5, 0x9f, 0x36, 0x86}
		},
	};

	int32 i;
	unsigned char tmp[36];
	psMd5Sha1_t	md;

	for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0]));  i++) {
		_psTraceInt("	MD5SHA1 known vector test %d... ", i + 1);
		psMd5Sha1Init(&md);
		psMd5Sha1Update(&md, (unsigned char*)tests[i].msg, (uint32)strlen(tests[i].msg));
		psMd5Sha1Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, 36) != 0) {
			_psTrace("FAILED: mem compare failure\n");
			return -1;
		} else {
			_psTrace("PASSED\n");
		}
	}
	return PS_SUCCESS;
}
#endif /* USE_MD5SHA1 */
/******************************************************************************/

/******************************************************************************/
#ifdef USE_MD5
int32 psMd5Test(void)
{
	static const struct {
		char *msg;
		unsigned char hash[16];
	} tests[] = {
		{ "",
		{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
			0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
		{ "a",
		{0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
			0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
		{ "abc",
		{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
			0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
		{ "message digest",
		{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
			0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
		{ "abcdefghijklmnopqrstuvwxyz",
		{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
			0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
		{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
		{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
			0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
		{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
		{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
			0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
		{ NULL, { 0 } }
	};

	int32 i;
	unsigned char tmp[MD5_HASHLEN];
	psMd5_t	md;

	for (i = 0; tests[i].msg != NULL; i++) {
	_psTraceInt("	MD5 known vector test %d... ", i + 1);
		psMd5Init(&md);
		psMd5Update(&md, (unsigned char *)tests[i].msg,
			(uint32)strlen(tests[i].msg));
		psMd5Final(&md, tmp);
		if (memcmp(tmp, tests[i].hash, MD5_HASHLEN) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		}
		_psTrace("PASSED\n");
	}
	return PS_SUCCESS;
}
#endif /* USE_MD5 */
/******************************************************************************/

/******************************************************************************/
#ifdef  USE_MD4
int32 psMd4Test(void)
{
	static const struct md4_test_case {
		char *input;
		unsigned char digest[16];
	} cases[] = {
		{ "",
		  {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
		   0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
		{ "a",
		  {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
		   0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
		{ "abc",
		  {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
		   0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
		{ "message digest",
		  {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
		   0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
		{ "abcdefghijklmnopqrstuvwxyz",
		  {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
		   0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
		{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
		  {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
		   0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
		{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
		  {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
		   0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
	};
	int32 i;
	psMd4_t md;
	unsigned char digest[16];

	for(i = 0; i < (int32)(sizeof(cases) / sizeof(cases[0])); i++) {
		_psTraceInt("	MD4 known vector test %d... ", i + 1);
		psMd4Init(&md);
		psMd4Update(&md, (unsigned char *)cases[i].input,
			(uint32)strlen(cases[i].input));
		psMd4Final(&md, digest);
		if (memcmp(digest, cases[i].digest, 16) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		}
		_psTrace("PASSED\n");
	}
	return PS_SUCCESS;
}
#endif /* USE_MD4 */
/******************************************************************************/

/******************************************************************************/
#ifdef USE_MD2
int32 psMd2Test(void)
{
	static const struct {
		char *msg;
		unsigned char md[16];
	} tests[] = {
		{ "",
			{0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d,
			0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73}
		},
		{ "a",
			{0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72,
			0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1}
		},
		{ "message digest",
			{0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b,
			0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0}
		},
		{ "abcdefghijklmnopqrstuvwxyz",
			{0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,
			0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b}
		},
		{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
			{0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,
			0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd}
		},
		{	"1234567890123456789012345678901234567890"
			"1234567890123456789012345678901234567890",
			{0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d,
			0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8}
		}
	};
	int32 i;
	psMd2_t md;
	unsigned char buf[16];

	for (i = 0; i < (int32)(sizeof(tests) / sizeof(tests[0])); i++) {
		_psTraceInt("	MD2 known vector test %d... ", i + 1);
		psMd2Init(&md);
		psMd2Update(&md, (unsigned char*)tests[i].msg,
			(uint32)strlen(tests[i].msg));
		psMd2Final(&md, buf);
		if (memcmp(buf, tests[i].md, 16) != 0) {
			_psTrace("FAILED: memcmp\n");
			return -1;
		}
		_psTrace("PASSED\n");
	}
	return PS_SUCCESS;
}
#endif /* USE_MD2 */
/******************************************************************************/


/******************************************************************************/
#ifdef USE_RSA

typedef void pkaCmdInfo_t;

/* Sample keys and certs in memory for RSA testing */
#include "../../testkeys/RSA/1024_RSA.h"
#include "../../testkeys/RSA/1024_RSA_KEY.h"
#include "../../testkeys/RSA/2048_RSA.h"
#include "../../testkeys/RSA/2048_RSA_KEY.h"
#include "../../testkeys/RSA/3072_RSA.h"
#include "../../testkeys/RSA/3072_RSA_KEY.h"
#include "../../testkeys/RSA/4096_RSA.h"
#include "../../testkeys/RSA/4096_RSA_KEY.h"

struct {
	uint16_t			size;		/* Size of public key exponent in bytes */
	const unsigned char	*key;		/* PKCS#1 key string */
	const unsigned char	*cert;		/* X.509 cert string */
	uint16_t			keysize;	/* Length of PKCS#1 key string */
	uint16_t			certsize;	/* Length of X.509 cert string */
} rsa[3] = {
	{ 128, RSA1024KEY, RSA1024, sizeof(RSA1024KEY), sizeof(RSA1024) },
	{ 256, RSA2048KEY, RSA2048, sizeof(RSA2048KEY), sizeof(RSA2048) },
	{ 512, RSA4096KEY, RSA4096, sizeof(RSA4096KEY), sizeof(RSA4096) }
};

static int32 psRsaEncryptTest(void)
{
	psPool_t		*pool = NULL;
	psRsaKey_t		privkey;
	pkaCmdInfo_t	*pkaInfo;
#ifdef USE_CERT_PARSE
	psX509Cert_t	*cert;
#endif /* USE_CERT_PARSE */
	unsigned char   out[512];	/* Large enough to hold 4096 bits of output */
	unsigned char   in[] = "hello";
	unsigned char   decrypted[6];
	int				i;

	pkaInfo = NULL;

	for (i = 0;
		i < sizeof(rsa)/sizeof(rsa[0]) && rsa[i].size >= (MIN_RSA_BITS / 8);
		i++) {
		_psTraceInt("	%d bit test...", rsa[i].size * 8);

	/* Start with getting both key halfs from the same source */
	if (psRsaInitKey(pool, &privkey) < 0) {
		return -1;
	}
	if (psRsaParsePkcs1PrivKey(pool, rsa[i].key, rsa[i].keysize, &privkey) < 0) {
		return -1;
	}
	psRsaEncryptPub(pool, &privkey, in, sizeof(in), out, rsa[i].size, pkaInfo);
	psRsaDecryptPriv(pool, &privkey, out, rsa[i].size, decrypted,
		sizeof(decrypted), pkaInfo);
	if (memcmp(decrypted, "hello", 5) != 0) {
		_psTrace("RSA failure: mem compare failure 1\n");
		psRsaClearKey(&privkey);
		continue;
	}
	psRsaClearKey(&privkey);
	memset(decrypted, 0x0, sizeof(decrypted));
	memset(out, 0x0, sizeof(out));

#ifdef USE_CERT_PARSE
	/* Get the public key from the cert */
	psRsaInitKey(pool, &privkey);
	psRsaParsePkcs1PrivKey(pool, rsa[i].key, rsa[i].keysize, &privkey);
	psX509ParseCert(pool, rsa[i].cert, rsa[i].certsize, &cert, 0);
	psRsaEncryptPub(pool, &cert->publicKey.key.rsa, in, sizeof(in), out,
		rsa[i].size, pkaInfo);
	psRsaDecryptPriv(pool, &privkey, out, rsa[i].size, decrypted,
		sizeof(decrypted), pkaInfo);
	if (memcmp(decrypted, "hello", 5) != 0) {
		psRsaClearKey(&privkey);
		psX509FreeCert(cert);
		_psTrace("RSA failure: mem compare failure 2\n");
		continue;
	}
	psRsaClearKey(&privkey);
	psX509FreeCert(cert);
	memset(decrypted, 0x0, sizeof(decrypted));
	memset(out, 0x0, sizeof(out));
#endif /* USE_CERT_PARSE */

	_psTrace(" PASSED\n");

	} /* key loop */

	return PS_SUCCESS;
}

/* Test RSA Signing, using RSA-2048 and SHA-256. */
static int32 psRsaSignTest(void)
{
	psPool_t *pool = NULL;
	unsigned char   in[32] = "helloworldhelloworldhelloworld1";
	unsigned char   out[512];
	unsigned char   decrypted[32];
	psRsaKey_t		privkey;
	pkaCmdInfo_t	*pkaInfo;
	int32_t rc;
	int i;

	pkaInfo = NULL;

	for (i = 0;
		i < sizeof(rsa)/sizeof(rsa[0]) && rsa[i].size >= (MIN_RSA_BITS / 8);
		i++) {
		_psTraceInt("	%d bit test...", rsa[i].size * 8);

	psRsaInitKey(pool, &privkey);
	psRsaParsePkcs1PrivKey(pool, rsa[i].key, rsa[i].keysize, &privkey);
	if (psRsaEncryptPriv(pool, &privkey, in, sizeof(in), out, rsa[i].size,
			pkaInfo) < 0) {
		psRsaClearKey(&privkey);
		return PS_FAILURE;
	}

		rc = psRsaDecryptPub(pool, &privkey, out, rsa[i].size, decrypted,
							sizeof(decrypted), pkaInfo);
		if (rc < 0) {
			_psTraceInt(" psRsaDecryptPub failure (%d)\n", rc);
			psRsaClearKey(&privkey);
			return PS_FAILURE;
		}
		if (memcmp(decrypted, in, sizeof(in)) != 0) {
			_psTraceStr("RSA failure: mem compare failure (%s)\n",
						(const char*)decrypted);
			psRsaClearKey(&privkey);
			return PS_FAILURE;
		}

		psRsaClearKey(&privkey);
		_psTrace(" PASSED\n");

	} /* key loop */

	return PS_SUCCESS;
}


/******************************************************************************/
#ifdef USE_PKCS1_OAEP
/* OAEP-VEC.TXT from RSA PKCS#1 web page */
static unsigned char key1N[] = {
	0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8,
	0x60, 0xf1, 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55,
	0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0,
	0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85,
	0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5,
	0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58,
	0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55,
	0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14,
	0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66,
	0x7b, 0xb3, 0xd4, 0x24, 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf,
	0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb
};
static unsigned char key1e[] = {0x01, 0x00, 0x01};

static unsigned char key1d[] = {
	0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73,
	0x16, 0xac, 0xa8, 0x5c, 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf,
	0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd, 0x8e, 0x25, 0x8d, 0xf9,
	0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b,
	0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5,
	0xaf, 0x0e, 0x7f, 0x55, 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26,
	0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73, 0x2c, 0x48, 0x31, 0x16,
	0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf,
	0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7,
	0x36, 0x9b, 0x31, 0xde, 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd,
	0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1
};

static unsigned char key1p[] = {
	0xd3, 0x27, 0x37, 0xe7, 0x26, 0x7f, 0xfe, 0x13, 0x41, 0xb2, 0xd5, 0xc0,
	0xd1, 0x50, 0xa8, 0x1b, 0x58, 0x6f, 0xb3, 0x13, 0x2b, 0xed, 0x2f, 0x8d,
	0x52, 0x62, 0x86, 0x4a, 0x9c, 0xb9, 0xf3, 0x0a, 0xf3, 0x8b, 0xe4, 0x48,
	0x59, 0x8d, 0x41, 0x3a, 0x17, 0x2e, 0xfb, 0x80, 0x2c, 0x21, 0xac, 0xf1,
	0xc1, 0x1c, 0x52, 0x0c, 0x2f, 0x26, 0xa4, 0x71, 0xdc, 0xad, 0x21, 0x2e,
	0xac, 0x7c, 0xa3, 0x9d
};

static unsigned char key1q[] = {
	0xcc, 0x88, 0x53, 0xd1, 0xd5, 0x4d, 0xa6, 0x30, 0xfa, 0xc0, 0x04, 0xf4,
	0x71, 0xf2, 0x81, 0xc7, 0xb8, 0x98, 0x2d, 0x82, 0x24, 0xa4, 0x90, 0xed,
	0xbe, 0xb3, 0x3d, 0x3e, 0x3d, 0x5c, 0xc9, 0x3c, 0x47, 0x65, 0x70, 0x3d,
	0x1d, 0xd7, 0x91, 0x64, 0x2f, 0x1f, 0x11, 0x6a, 0x0d, 0xd8, 0x52, 0xbe,
	0x24, 0x19, 0xb2, 0xaf, 0x72, 0xbf, 0xe9, 0xa0, 0x30, 0xe8, 0x60, 0xb0,
	0x28, 0x8b, 0x5d, 0x77
};

static unsigned char key1dP[] = {
	0x0e, 0x12, 0xbf, 0x17, 0x18, 0xe9, 0xce, 0xf5, 0x59, 0x9b, 0xa1, 0xc3,
	0x88, 0x2f, 0xe8, 0x04, 0x6a, 0x90, 0x87, 0x4e, 0xef, 0xce, 0x8f, 0x2c,
	0xcc, 0x20, 0xe4, 0xf2, 0x74, 0x1f, 0xb0, 0xa3, 0x3a, 0x38, 0x48, 0xae,
	0xc9, 0xc9, 0x30, 0x5f, 0xbe, 0xcb, 0xd2, 0xd7, 0x68, 0x19, 0x96, 0x7d,
	0x46, 0x71, 0xac, 0xc6, 0x43, 0x1e, 0x40, 0x37, 0x96, 0x8d, 0xb3, 0x78,
	0x78, 0xe6, 0x95, 0xc1
};

static unsigned char key1dQ[] = {
	0x95, 0x29, 0x7b, 0x0f, 0x95, 0xa2, 0xfa, 0x67, 0xd0, 0x07, 0x07, 0xd6,
	0x09, 0xdf, 0xd4, 0xfc, 0x05, 0xc8, 0x9d, 0xaf, 0xc2, 0xef, 0x6d, 0x6e,
	0xa5, 0x5b, 0xec, 0x77, 0x1e, 0xa3, 0x33, 0x73, 0x4d, 0x92, 0x51, 0xe7,
	0x90, 0x82, 0xec, 0xda, 0x86, 0x6e, 0xfe, 0xf1, 0x3c, 0x45, 0x9e, 0x1a,
	0x63, 0x13, 0x86, 0xb7, 0xe3, 0x54, 0xc8, 0x99, 0xf5, 0xf1, 0x12, 0xca,
	0x85, 0xd7, 0x15, 0x83
};

static unsigned char key1qP[] = {
	0x4f, 0x45, 0x6c, 0x50, 0x24, 0x93, 0xbd, 0xc0, 0xed, 0x2a, 0xb7, 0x56,
	0xa3, 0xa6, 0xed, 0x4d, 0x67, 0x35, 0x2a, 0x69, 0x7d, 0x42, 0x16, 0xe9,
	0x32, 0x12, 0xb1, 0x27, 0xa6, 0x3d, 0x54, 0x11, 0xce, 0x6f, 0xa9, 0x8d,
	0x5d, 0xbe, 0xfd, 0x73, 0x26, 0x3e, 0x37, 0x28, 0x14, 0x27, 0x43, 0x81,
	0x81, 0x66, 0xed, 0x7d, 0xd6, 0x36, 0x87, 0xdd, 0x2a, 0x8c, 0xa1, 0xd2,
	0xf4, 0xfb, 0xd8, 0xe1
};

static unsigned char key1TestMsg[] = {
	0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda,
	0x9e, 0xf9, 0x53, 0x23, 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00,
	0x4a, 0xfe, 0xfe, 0x34
};

static unsigned char key1SeedPad[] = {
	0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69, 0x77, 0x6a, 0x33, 0xe9,
	0x6b, 0xad, 0x48, 0xe1, 0xdd, 0xa0, 0xa5, 0xef
};

static unsigned char key1EncryptedResult[] = {
	0x35, 0x4f, 0xe6, 0x7b, 0x4a, 0x12, 0x6d, 0x5d, 0x35, 0xfe, 0x36, 0xc7,
	0x77, 0x79, 0x1a, 0x3f, 0x7b, 0xa1, 0x3d, 0xef, 0x48, 0x4e, 0x2d, 0x39,
	0x08, 0xaf, 0xf7, 0x22, 0xfa, 0xd4, 0x68, 0xfb, 0x21, 0x69, 0x6d, 0xe9,
	0x5d, 0x0b, 0xe9, 0x11, 0xc2, 0xd3, 0x17, 0x4f, 0x8a, 0xfc, 0xc2, 0x01,
	0x03, 0x5f, 0x7b, 0x6d, 0x8e, 0x69, 0x40, 0x2d, 0xe5, 0x45, 0x16, 0x18,
	0xc2, 0x1a, 0x53, 0x5f, 0xa9, 0xd7, 0xbf, 0xc5, 0xb8, 0xdd, 0x9f, 0xc2,
	0x43, 0xf8, 0xcf, 0x92, 0x7d, 0xb3, 0x13, 0x22, 0xd6, 0xe8, 0x81, 0xea,
	0xa9, 0x1a, 0x99, 0x61, 0x70, 0xe6, 0x57, 0xa0, 0x5a, 0x26, 0x64, 0x26,
	0xd9, 0x8c, 0x88, 0x00, 0x3f, 0x84, 0x77, 0xc1, 0x22, 0x70, 0x94, 0xa0,
	0xd9, 0xfa, 0x1e, 0x8c, 0x40, 0x24, 0x30, 0x9c, 0xe1, 0xec, 0xcc, 0xb5,
	0x21, 0x00, 0x35, 0xd4, 0x7a, 0xc7, 0x2e, 0x8a
};

static int32 psRsaOaepVectorTest(void)
{
	psPool_t		*pool = NULL;
	psRsaKey_t		key1;
	pstm_int		mpN, mpe, mpd, mpp, mpq, mpdP, mpdQ, mpqP;
	uint32			digSize;
	uint16_t		outLen;
	unsigned char	*outOaep, *outRsaE, *outRsaD;
	int32			ret;

	outOaep = outRsaE = outRsaD = NULL;
	digSize = sizeof(pstm_digit);

	if (pstm_init_for_read_unsigned_bin(pool, &mpN, sizeof(key1N) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpN, key1N, sizeof(key1N));

	if (pstm_init_for_read_unsigned_bin(pool, &mpe, sizeof(key1e) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpe, key1e, sizeof(key1e));

	if (pstm_init_for_read_unsigned_bin(pool, &mpd, sizeof(key1d) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpd, key1d, sizeof(key1d));

	if (pstm_init_for_read_unsigned_bin(pool, &mpp, sizeof(key1p) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpp, key1p, sizeof(key1p));

	if (pstm_init_for_read_unsigned_bin(NULL, &mpq, sizeof(key1q) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpq, key1q, sizeof(key1q));

	if (pstm_init_for_read_unsigned_bin(pool, &mpdP, sizeof(key1dP) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpdP, key1dP, sizeof(key1dP));

	if (pstm_init_for_read_unsigned_bin(pool, &mpdQ, sizeof(key1dQ) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpdQ, key1dQ, sizeof(key1dQ));

	if (pstm_init_for_read_unsigned_bin(pool, &mpqP, sizeof(key1qP) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpqP, key1qP, sizeof(key1qP));

	key1.e = mpe;
	key1.N = mpN;
	key1.d = mpd;
	key1.p = mpp;
	key1.q = mpq;
	key1.dP = mpdP;
	key1.dQ = mpdQ;
	key1.qP = mpqP;
	key1.optimized = 1;
	outLen = key1.size = pstm_unsigned_bin_size(&mpN);

	outOaep = psMalloc(pool, outLen);
	pkcs1OaepEncode(pool, key1TestMsg, sizeof(key1TestMsg), NULL, 0,
		key1SeedPad, sizeof(key1SeedPad), key1.size * CHAR_BIT, 0, outOaep,
		&outLen);

	outRsaE = psMalloc(pool, outLen);
	psRsaCrypt(pool, &key1, outOaep, outLen, outRsaE, &outLen, PS_PUBKEY, NULL);

	if (memcmp(outRsaE, key1EncryptedResult, outLen) != 0) {
		_psTrace("ERROR in encrypting key1 RSAES_OAEP vector test\n");
		ret = PS_FAILURE;
		goto LBL_ERR;
	}

	outRsaD = psMalloc(pool, outLen);
	psRsaCrypt(pool, &key1, outRsaE, outLen, outRsaD, &outLen, PS_PRIVKEY, NULL);

	memset(outOaep, 0x0, key1.size);
	pkcs1OaepDecode(pool, outRsaD, outLen, NULL, 0, key1.size * CHAR_BIT, 0,
		outOaep, &outLen);

	if ((outLen != sizeof(key1TestMsg)) || (memcmp(outOaep, key1TestMsg, outLen)
			!= 0)) {
		_psTrace("ERROR in decrypting key1 RSAES_OAEP vector test\n");
		ret = PS_FAILURE;
		goto LBL_ERR;
	}

/*
	Now just run a plaintext test of our choosing with the MD5 hash and label
*/
	outLen = key1.size;
	if (pkcs1OaepEncode(pool, (const unsigned char*)"Hello", 5,
			(const unsigned char*)"mylabel", 7,	NULL, 0,
			key1.size * CHAR_BIT, 1, outOaep, &outLen) < PS_SUCCESS) {
		_psTrace("ERROR encoding standard RSAES_OAEP vector test\n");
		ret = PS_FAILURE;
		goto LBL_ERR;
	}
	psRsaCrypt(pool, &key1, outOaep, outLen, outRsaE, &outLen, PS_PUBKEY, NULL);

	psRsaCrypt(pool, &key1, outRsaE, outLen, outRsaD, &outLen, PS_PRIVKEY, NULL);
	pkcs1OaepDecode(pool, outRsaD, outLen, (const unsigned char*)"mylabel", 7,
		key1.size * CHAR_BIT, 1, outOaep, &outLen);

	if (memcmp(outOaep, "Hello", outLen) != 0) {
		_psTrace("ERROR in standard RSAES_OAEP vector test\n");
		ret = PS_FAILURE;
		goto LBL_ERR;
	}

	_psTrace("	PASSED\n");
	ret = PS_SUCCESS;
LBL_ERR:
	pstm_clear(&key1.N);
	pstm_clear(&key1.e);
	pstm_clear(&key1.d);
	pstm_clear(&key1.p);
	pstm_clear(&key1.q);
	pstm_clear(&key1.dP);
	pstm_clear(&key1.dQ);
	pstm_clear(&key1.qP);
	psFree(outOaep, pool);
	psFree(outRsaE, pool);
	psFree(outRsaD, pool);
	return ret;
}
#endif /* USE_PKCS1_OAEP */

/******************************************************************************/
#ifdef USE_PKCS1_PSS
#ifndef USE_PKCS1_PSS_VERIFY_ONLY /* Because PSS signing is used in this test. */
/* PSS-VEC.TXT from RSA PKCS#1 web page */
static unsigned char key2N[] = {
	0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51, 0x87, 0xdc,
	0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e, 0x36, 0xad, 0x52, 0xa4,
	0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a, 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56,
	0xff, 0xed, 0xb1, 0x62, 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3,
	0x94, 0xdf, 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
	0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d, 0x5b, 0x2b,
	0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77, 0xc0, 0x92, 0x1c, 0xb2,
	0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59, 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1,
	0x05, 0xac, 0xc2, 0xd3, 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38,
	0x6b, 0x6f, 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
	0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37
};
static unsigned char key2e[] = {0x01, 0x00, 0x01};

static unsigned char key2d[] = {
	0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51, 0xca, 0x9b,
	0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf, 0x88, 0x43, 0x40, 0xae,
	0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe, 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac,
	0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8,
	0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
	0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10, 0xce, 0x70,
	0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27, 0xa3, 0x95, 0x74, 0x50,
	0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c,
	0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3,
	0x4f, 0x9e, 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
	0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25
};

static unsigned char key2p[] = {
	0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73, 0xa3, 0x56,
	0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa, 0x72, 0xd5, 0x5c, 0x6e,
	0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96, 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc,
	0xcc, 0xa7, 0xea, 0xcb, 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1,
	0x53, 0x5b, 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
	0xda, 0x8e, 0x64, 0x43
};

static unsigned char key2q[] = {
	0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7, 0x5b, 0x90,
	0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f, 0xd2, 0x70, 0x01, 0x80,
	0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48, 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9,
	0xf1, 0x9d, 0x85, 0xba, 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc,
	0x72, 0x3e, 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
	0x9a, 0x67, 0x99, 0xfd
};

static unsigned char key2dP[] = {
	0x28, 0xfa, 0x13, 0x93, 0x86, 0x55, 0xbe, 0x1f, 0x8a, 0x15, 0x9c, 0xba,
	0xca, 0x5a, 0x72, 0xea, 0x19, 0x0c, 0x30, 0x08, 0x9e, 0x19, 0xcd, 0x27,
	0x4a, 0x55, 0x6f, 0x36, 0xc4, 0xf6, 0xe1, 0x9f, 0x55, 0x4b, 0x34, 0xc0,
	0x77, 0x79, 0x04, 0x27, 0xbb, 0xdd, 0x8d, 0xd3, 0xed, 0xe2, 0x44, 0x83,
	0x28, 0xf3, 0x85, 0xd8, 0x1b, 0x30, 0xe8, 0xe4, 0x3b, 0x2f, 0xff, 0xa0,
	0x27, 0x86, 0x19, 0x79
};

static unsigned char key2dQ[] = {
	0x1a, 0x8b, 0x38, 0xf3, 0x98, 0xfa, 0x71, 0x20, 0x49, 0x89, 0x8d, 0x7f,
	0xb7, 0x9e, 0xe0, 0xa7, 0x76, 0x68, 0x79, 0x12, 0x99, 0xcd, 0xfa, 0x09,
	0xef, 0xc0, 0xe5, 0x07, 0xac, 0xb2, 0x1e, 0xd7, 0x43, 0x01, 0xef, 0x5b,
	0xfd, 0x48, 0xbe, 0x45, 0x5e, 0xae, 0xb6, 0xe1, 0x67, 0x82, 0x55, 0x82,
	0x75, 0x80, 0xa8, 0xe4, 0xe8, 0xe1, 0x41, 0x51, 0xd1, 0x51, 0x0a, 0x82,
	0xa3, 0xf2, 0xe7, 0x29
};

static unsigned char key2qP[] = {
	0x27, 0x15, 0x6a, 0xba, 0x41, 0x26, 0xd2, 0x4a, 0x81, 0xf3, 0xa5, 0x28,
	0xcb, 0xfb, 0x27, 0xf5, 0x68, 0x86, 0xf8, 0x40, 0xa9, 0xf6, 0xe8, 0x6e,
	0x17, 0xa4, 0x4b, 0x94, 0xfe, 0x93, 0x19, 0x58, 0x4b, 0x8e, 0x22, 0xfd,
	0xde, 0x1e, 0x5a, 0x2e, 0x3b, 0xd8, 0xaa, 0x5b, 0xa8, 0xd8, 0x58, 0x41,
	0x94, 0xeb, 0x21, 0x90, 0xac, 0xf8, 0x32, 0xb8, 0x47, 0xf1, 0x3a, 0x3d,
	0x24, 0xa7, 0x9f, 0x4d
};

static unsigned char key2TestMsg[] = {
	0xcd, 0xc8, 0x7d, 0xa2, 0x23, 0xd7, 0x86, 0xdf, 0x3b, 0x45, 0xe0, 0xbb,
	0xbc, 0x72, 0x13, 0x26, 0xd1, 0xee, 0x2a, 0xf8, 0x06, 0xcc, 0x31, 0x54,
	0x75, 0xcc, 0x6f, 0x0d, 0x9c, 0x66, 0xe1, 0xb6, 0x23, 0x71, 0xd4, 0x5c,
	0xe2, 0x39, 0x2e, 0x1a, 0xc9, 0x28, 0x44, 0xc3, 0x10, 0x10, 0x2f, 0x15,
	0x6a, 0x0d, 0x8d, 0x52, 0xc1, 0xf4, 0xc4, 0x0b, 0xa3, 0xaa, 0x65, 0x09,
	0x57, 0x86, 0xcb, 0x76, 0x97, 0x57, 0xa6, 0x56, 0x3b, 0xa9, 0x58, 0xfe,
	0xd0, 0xbc, 0xc9, 0x84, 0xe8, 0xb5, 0x17, 0xa3, 0xd5, 0xf5, 0x15, 0xb2,
	0x3b, 0x8a, 0x41, 0xe7, 0x4a, 0xa8, 0x67, 0x69, 0x3f, 0x90, 0xdf, 0xb0,
	0x61, 0xa6, 0xe8, 0x6d, 0xfa, 0xae, 0xe6, 0x44, 0x72, 0xc0, 0x0e, 0x5f,
	0x20, 0x94, 0x57, 0x29, 0xcb, 0xeb, 0xe7, 0x7f, 0x06, 0xce, 0x78, 0xe0,
	0x8f, 0x40, 0x98, 0xfb, 0xa4, 0x1f, 0x9d, 0x61, 0x93, 0xc0, 0x31, 0x7e,
	0x8b, 0x60, 0xd4, 0xb6, 0x08, 0x4a, 0xcb, 0x42, 0xd2, 0x9e, 0x38, 0x08,
	0xa3, 0xbc, 0x37, 0x2d, 0x85, 0xe3, 0x31, 0x17, 0x0f, 0xcb, 0xf7, 0xcc,
	0x72, 0xd0, 0xb7, 0x1c, 0x29, 0x66, 0x48, 0xb3, 0xa4, 0xd1, 0x0f, 0x41,
	0x62, 0x95, 0xd0, 0x80, 0x7a, 0xa6, 0x25, 0xca, 0xb2, 0x74, 0x4f, 0xd9,
	0xea, 0x8f, 0xd2, 0x23, 0xc4, 0x25, 0x37, 0x02, 0x98, 0x28, 0xbd, 0x16,
	0xbe, 0x02, 0x54, 0x6f, 0x13, 0x0f, 0xd2, 0xe3, 0x3b, 0x93, 0x6d, 0x26,
	0x76, 0xe0, 0x8a, 0xed, 0x1b, 0x73, 0x31, 0x8b, 0x75, 0x0a, 0x01, 0x67,
	0xd0
};

static unsigned char key2salt[] = {
	0xde, 0xe9, 0x59, 0xc7, 0xe0, 0x64, 0x11, 0x36, 0x14, 0x20, 0xff, 0x80,
	0x18, 0x5e, 0xd5, 0x7f, 0x3e, 0x67, 0x76, 0xaf
};

static unsigned char key2sig[] = {
	0x90, 0x74, 0x30, 0x8f, 0xb5, 0x98, 0xe9, 0x70, 0x1b, 0x22, 0x94, 0x38,
	0x8e, 0x52, 0xf9, 0x71, 0xfa, 0xac, 0x2b, 0x60, 0xa5, 0x14, 0x5a, 0xf1,
	0x85, 0xdf, 0x52, 0x87, 0xb5, 0xed, 0x28, 0x87, 0xe5, 0x7c, 0xe7, 0xfd,
	0x44, 0xdc, 0x86, 0x34, 0xe4, 0x07, 0xc8, 0xe0, 0xe4, 0x36, 0x0b, 0xc2,
	0x26, 0xf3, 0xec, 0x22, 0x7f, 0x9d, 0x9e, 0x54, 0x63, 0x8e, 0x8d, 0x31,
	0xf5, 0x05, 0x12, 0x15, 0xdf, 0x6e, 0xbb, 0x9c, 0x2f, 0x95, 0x79, 0xaa,
	0x77, 0x59, 0x8a, 0x38, 0xf9, 0x14, 0xb5, 0xb9, 0xc1, 0xbd, 0x83, 0xc4,
	0xe2, 0xf9, 0xf3, 0x82, 0xa0, 0xd0, 0xaa, 0x35, 0x42, 0xff, 0xee, 0x65,
	0x98, 0x4a, 0x60, 0x1b, 0xc6, 0x9e, 0xb2, 0x8d, 0xeb, 0x27, 0xdc, 0xa1,
	0x2c, 0x82, 0xc2, 0xd4, 0xc3, 0xf6, 0x6c, 0xd5, 0x00, 0xf1, 0xff, 0x2b,
	0x99, 0x4d, 0x8a, 0x4e, 0x30, 0xcb, 0xb3, 0x3c
};

static int32 psRsaPssVectorTest(void)
{
	psPool_t		*pool = NULL;
	psRsaKey_t		key1;
	pstm_int		mpN, mpe, mpd, mpp, mpq, mpdP, mpdQ, mpqP;
	uint32			digSize, outLen;
	uint16_t                outLen16;
	unsigned char	*outPss, *outRsaE, *outRsaD;
	psSha1_t		md;
	unsigned char	hash[SHA1_HASH_SIZE];
	int32			result, ret;

	outPss = outRsaE = outRsaD = NULL;

	digSize = sizeof(pstm_digit);

	if (pstm_init_for_read_unsigned_bin(pool, &mpN, sizeof(key2N) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpN, key2N, sizeof(key2N));

	if (pstm_init_for_read_unsigned_bin(pool, &mpe, sizeof(key2e) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpe, key2e, sizeof(key2e));

	if (pstm_init_for_read_unsigned_bin(pool, &mpd, sizeof(key2d) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpd, key2d, sizeof(key2d));

	if (pstm_init_for_read_unsigned_bin(pool, &mpp, sizeof(key2p) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpp, key2p, sizeof(key2p));

	if (pstm_init_for_read_unsigned_bin(pool, &mpq, sizeof(key2q) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpq, key2q, sizeof(key2q));

	if (pstm_init_for_read_unsigned_bin(pool, &mpdP, sizeof(key2dP) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpdP, key2dP, sizeof(key2dP));

	if (pstm_init_for_read_unsigned_bin(pool, &mpdQ, sizeof(key2dQ) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpdQ, key2dQ, sizeof(key2dQ));

	if (pstm_init_for_read_unsigned_bin(pool, &mpqP, sizeof(key2qP) + digSize)
			!= PS_SUCCESS) {
		return PS_FAILURE;
	}
	pstm_read_unsigned_bin(&mpqP, key2qP, sizeof(key2qP));

	key1.e = mpe;
	key1.N = mpN;
	key1.d = mpd;
	key1.p = mpp;
	key1.q = mpq;
	key1.dP = mpdP;
	key1.dQ = mpdQ;
	key1.qP = mpqP;
	key1.optimized = 1;
	outLen = key1.size = pstm_unsigned_bin_size(&mpN);

	/* First take SHA-1 hash of test message */
	psSha1Init(&md);
	psSha1Update(&md, key2TestMsg, sizeof(key2TestMsg));
	psSha1Final(&md, hash);

	/* Then PSS */
	outPss = psMalloc(pool, outLen);
	outLen16 = (uint16_t) outLen;
	pkcs1PssEncode(pool, hash, SHA1_HASH_SIZE, key2salt, sizeof(key2salt),
			0,	key1.size * CHAR_BIT, outPss, &outLen16);
	outLen = outLen16;

	outRsaE = psMalloc(pool, outLen);
	/* Then sign */
	psRsaCrypt(pool, &key1, outPss, outLen, outRsaE, &outLen16, PS_PRIVKEY,
			   NULL);
	outLen = outLen16;

	/* Check against vector */
	if (memcmp(outRsaE, key2sig, outLen) != 0) {
		_psTrace("ERROR in encrypting key1 RSASSA_PSS vector test\n");
		ret = PS_FAILURE;
		goto LBL_ERR;
	}
	/* Verify */
	outRsaD = psMalloc(pool, outLen);
	/* Decrypt */
	outLen16 = (uint16_t) outLen;
	psRsaCrypt(pool, &key1, outRsaE, outLen, outRsaD, &outLen16, PS_PUBKEY, NULL);
	outLen = outLen16;
	/* PSS decode */
	pkcs1PssDecode(pool, hash, SHA1_HASH_SIZE, outRsaD, outLen,
		sizeof(key2salt), 0, key1.size * CHAR_BIT, &result);

	if (result != 1) {
		_psTrace("ERROR in decrypting key1 RSASSA_PSS vector test\n");
		ret = PS_FAILURE;
		goto LBL_ERR;
	}

	_psTrace("	PASSED\n");
	ret = PS_SUCCESS;

LBL_ERR:
	pstm_clear(&key1.N);
	pstm_clear(&key1.e);
	pstm_clear(&key1.d);
	pstm_clear(&key1.p);
	pstm_clear(&key1.q);
	pstm_clear(&key1.dP);
	pstm_clear(&key1.dQ);
	pstm_clear(&key1.qP);
	psFree(outRsaD, pool);
	psFree(outPss, pool);
	psFree(outRsaE, pool);
	return ret;
}
#endif /* USE_PKCS1_PSS_VERIFY_ONLY */
#endif /* USE_PKCS1_PSS */

#endif /* USE_RSA */

#ifdef USE_HMAC
#ifdef USE_HMAC_TLS
static int nohmactls = 0;
#endif

static int32 psHmacVectorTestSimple(void)
{
	unsigned char res[20];
	unsigned char res2[20];
    psHmacSha1_t ctx;
	int32_t rv;
	const char *data1 = "Hi There";

	unsigned char key1[] = {
		0x0b, 0x0b, 0x0b, 0x0b,
		0x0b, 0x0b, 0x0b, 0x0b,
		0x0b, 0x0b, 0x0b, 0x0b,
		0x0b, 0x0b, 0x0b, 0x0b,
		0x0b, 0x0b, 0x0b, 0x0b
	};
	const unsigned char res1[] = {
		0xb6, 0x17, 0x31, 0x86,
		0x55, 0x05, 0x72, 0x64,
		0xe2, 0x8b, 0xc0, 0xb6,
		0xfb, 0x37, 0x8c, 0x8e,
		0xf1, 0x46, 0xbe, 0x00
	};
    uint16_t keyLen = (uint16_t) sizeof(key1);

	_psTraceInt("	SHA-1 known vector test %d... ", 1);

	/* Try single-call */
	rv = psHmacSha1(key1, keyLen, (unsigned char *) data1,
					(uint32_t) strlen(data1), res2,
					key1, &keyLen);
	if (rv != PS_SUCCESS) {
		_psTraceInt("FAILED: Single-part HMAC KAT execution failure (rv=%d)\n",
					(int)rv);
		return PS_FAILURE;
	}
	if (memcmp(res1, res2, 20) != 0) {
		_psTrace("FAILED: Single-part HMAC KAT mismatch\n");
		return PS_FAILURE;
	}

#ifdef USE_HMAC_TLS
	/* Try single-call */
	memset(res2, 0, 20);
	rv = psHmacSha1Tls(key1, keyLen,
					   (unsigned char *) data1, 2,
					   (unsigned char *) data1 + 2, 4,
					   (unsigned char *) data1 + 6, 2, 2, res2);
	if (rv == PS_DISABLED_FEATURE_FAIL) {
		nohmactls = 1;
	} else if (rv != SHA1_HASH_SIZE) {
		_psTraceInt("FAILED: Single-part HMAC KAT execution failure (rv=%d)\n",
					(int)rv);
		return PS_FAILURE;
	} else if (memcmp(res1, res2, 20) != 0) {
		_psTrace("FAILED: Single-part HMAC KAT mismatch\n");
		return PS_FAILURE;
	}
#endif /* USE_HMAC_TLS */

	/* Try init-update-finish */
	rv = psHmacSha1Init(&ctx, key1, keyLen);
	psHmacSha1Update(&ctx, (unsigned char *) data1, (uint32_t) strlen(data1));
	(void)psHmacSha1Final(&ctx, res);
	if (memcmp(res, res1, 20) != 0) {
		_psTrace("FAILED: Init-Update-Finish HMAC KAT mismatch\n");
	}
	_psTrace("PASSED\n");
	return PS_SUCCESS;
}

static int test_hmac_vector_num_calls;

static int test_hmac_vector(int32 size,
							const unsigned char *key,
							size_t key_len,
							const unsigned char *din,
							size_t din_len,
							const unsigned char *dout,
							size_t dout_len,
							int32 should_succeed)
{
	unsigned char key_out[128];
	unsigned char md_res[64];
	uint16_t key_length = 0;
	int equals;
	int32 rv = PS_SUCCESS;
	psHmacSha1_t hmac_sha1_ctx;
	psHmacSha256_t hmac_sha256_ctx;
	psHmacSha384_t hmac_sha384_ctx;

	++test_hmac_vector_num_calls;

	/* Copy key, if it is short as short ones are not normally copied. */
	if (key_len <= 128) {
		memcpy(key_out, key, key_len);
		key = key_out;
	}
	key_length = (uint16_t)key_len;

	psAssert(size == 20 || size == 28 || size == 32 ||
			 size == 48);

	if (size == 20) {
		rv = psHmacSha1((unsigned char *) key, key_length,
						din, din_len,
						md_res,
						key_out, &key_length);
	} else if (size == 32) {
		rv = psHmacSha256((unsigned char *) key, key_length,
						  din, din_len,
						  md_res,
						  key_out, &key_length);
	} else if (size == 48) {
		rv = psHmacSha384((unsigned char *) key, key_length,
						  din, din_len,
						  md_res,
						  key_out, &key_length);
	}

	equals = (rv == PS_SUCCESS && memcmp(dout, md_res, size) == 0);
	if (equals != should_succeed)
	{
		_psTraceInt("FAILED: HMAC vector with %d bit key\n",
					8 * (int) key_len);
		return PS_FAILURE;
	}

	memset(md_res, 0, sizeof(md_res));

	if (size == 20) {
		rv = psHmacSha1Init(&hmac_sha1_ctx, key_out, key_length);
		psHmacSha1Update(&hmac_sha1_ctx, din, din_len);
		psHmacSha1Final(&hmac_sha1_ctx, md_res);
	} else if (size == 32) {
		rv = psHmacSha256Init(&hmac_sha256_ctx, key_out, key_length);
		psHmacSha256Update(&hmac_sha256_ctx, din, din_len);
		psHmacSha256Final(&hmac_sha256_ctx, md_res);
	} else if (size == 48) {
		rv = psHmacSha384Init(&hmac_sha384_ctx, key_out, key_length);
		psHmacSha384Update(&hmac_sha384_ctx, din, din_len);
		psHmacSha384Final(&hmac_sha384_ctx, md_res);
	}

	equals = (rv == PS_SUCCESS && memcmp(dout, md_res, size) == 0);
	if (equals != should_succeed)
	{
		_psTraceInt("FAILED: HMAC vector with %d bit key (multipart op)\n",
					8 * (int) key_len);
		return PS_FAILURE;
	}

#ifdef USE_HMAC_TLS
	/* Try single-call if suitable vector size. */

	if (size == 20 || din_len < 13 || key_len > 64 || nohmactls == 1)
		return 1;

	memset(md_res, 0, sizeof(md_res));
	if (din_len < 64)
	{
		int i;
		unsigned char tmp[164];
		memcpy(tmp, din, din_len);

		for(i = 0; i < 100; i++) {
			rv = psHmacSha2Tls(key, key_len,
							   (unsigned char *) din, 8,
							   (unsigned char *) din + 8, 5,
							   (unsigned char *) din + 13, din_len - 13,
							   din_len - 13 + i, md_res, size);

			if (rv != size) {
				_psTraceInt(
					"FAILED: Single-part HMAC KAT execution failure (rv=%d)\n",
					(int)rv);
				return PS_FAILURE;
			}

			if (memcmp(dout, md_res, size) != 0) {
				_psTrace("FAILED: Single-part HMAC KAT mismatch\n");
				return PS_FAILURE;
			}
		}
	}
	else
	{
		rv = psHmacSha2Tls(key, key_len,
						   (unsigned char *) din, 8,
						   (unsigned char *) din + 8, 5,
						   (unsigned char *) din + 13, din_len - 13,
						   din_len - 13, md_res, size);
	}

	if (rv != size) {
		_psTraceInt("FAILED: Single-part HMAC KAT execution failure (rv=%d)\n",
					(int)rv);
		return PS_FAILURE;
	}
	if (memcmp(dout, md_res, size) != 0) {
		_psTrace("FAILED: Single-part HMAC KAT mismatch\n");
		return PS_FAILURE;
	}
#endif /* USE_HMAC_TLS */

	return 1;
}

static int32 psHmacVectorTestsShared(int algo)
{
	int32 md;
	int32 e = 1;
	int32 res = PS_SUCCESS;
	int32 count = 0;

	/* SHA-1 */

	if (algo != 20)
		goto sha2_224;

	md = algo;

	/* key size: 14 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector14_key,
		       sizeof(hmac_sha1_vector14_key),
		       hmac_sha1_vector14_in,
		       sizeof(hmac_sha1_vector14_in),
		       hmac_sha1_vector14_out,
		       sizeof(hmac_sha1_vector14_out),
		       e);

	/* key size: 16 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector16_key,
		       sizeof(hmac_sha1_vector16_key),
		       hmac_sha1_vector16_in,
		       sizeof(hmac_sha1_vector16_in),
		       hmac_sha1_vector16_out,
		       sizeof(hmac_sha1_vector16_out),
		       e);

	/* key size: 20 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector20_key,
		       sizeof(hmac_sha1_vector20_key),
		       hmac_sha1_vector20_in,
		       sizeof(hmac_sha1_vector20_in),
		       hmac_sha1_vector20_out,
		       sizeof(hmac_sha1_vector20_out),
		       e);

	/* key size: 24 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector24_key,
		       sizeof(hmac_sha1_vector24_key),
		       hmac_sha1_vector24_in,
		       sizeof(hmac_sha1_vector24_in),
		       hmac_sha1_vector24_out,
		       sizeof(hmac_sha1_vector24_out),
		       e);

	/* key size: 28 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector28_key,
		       sizeof(hmac_sha1_vector28_key),
		       hmac_sha1_vector28_in,
		       sizeof(hmac_sha1_vector28_in),
		       hmac_sha1_vector28_out,
		       sizeof(hmac_sha1_vector28_out),
		       e);

	/* key size: 32 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector32_key,
		       sizeof(hmac_sha1_vector32_key),
		       hmac_sha1_vector32_in,
		       sizeof(hmac_sha1_vector32_in),
		       hmac_sha1_vector32_out,
		       sizeof(hmac_sha1_vector32_out),
		       e);

	/* key size: 48 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector48_key,
		       sizeof(hmac_sha1_vector48_key),
		       hmac_sha1_vector48_in,
		       sizeof(hmac_sha1_vector48_in),
		       hmac_sha1_vector48_out,
		       sizeof(hmac_sha1_vector48_out),
		       e);

	/* key size: 64 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector64_key,
		       sizeof(hmac_sha1_vector64_key),
		       hmac_sha1_vector64_in,
		       sizeof(hmac_sha1_vector64_in),
		       hmac_sha1_vector64_out,
		       sizeof(hmac_sha1_vector64_out),
		       e);

	/* key size: 128 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector128_key,
		       sizeof(hmac_sha1_vector128_key),
		       hmac_sha1_vector128_in,
		       sizeof(hmac_sha1_vector128_in),
		       hmac_sha1_vector128_out,
		       sizeof(hmac_sha1_vector128_out),
		       e);

	/* key size: 256 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector256_key,
		       sizeof(hmac_sha1_vector256_key),
		       hmac_sha1_vector256_in,
		       sizeof(hmac_sha1_vector256_in),
		       hmac_sha1_vector256_out,
		       sizeof(hmac_sha1_vector256_out),
		       e);

	/* key size: 512 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector512_key,
		       sizeof(hmac_sha1_vector512_key),
		       hmac_sha1_vector512_in,
		       sizeof(hmac_sha1_vector512_in),
		       hmac_sha1_vector512_out,
		       sizeof(hmac_sha1_vector512_out),
		       e);

	/* key size: 1024 bytes */
	count += test_hmac_vector(md,
		       hmac_sha1_vector1024_key,
		       sizeof(hmac_sha1_vector1024_key),
		       hmac_sha1_vector1024_in,
		       sizeof(hmac_sha1_vector1024_in),
		       hmac_sha1_vector1024_out,
		       sizeof(hmac_sha1_vector1024_out),
		       e);

	/* multiblock test */
	count += test_hmac_vector(md,
		       hmac_vector1024_multiblock_key,
		       sizeof(hmac_vector1024_multiblock_key),
		       hmac_vector1024_multiblock_in,
		       sizeof(hmac_vector1024_multiblock_in),
		       hmac_sha1_vector1024_multiblock_out,
		       sizeof(hmac_sha1_vector1024_multiblock_out),
		       e);

	/* SHA-224 */
sha2_224:

	if (algo != 28)
		goto sha2_256;

	md = algo;

	/* key size: 14 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector14_key,
		       sizeof(hmac_sha224_vector14_key),
		       hmac_sha224_vector14_in,
		       sizeof(hmac_sha224_vector14_in),
		       hmac_sha224_vector14_out,
		       sizeof(hmac_sha224_vector14_out),
		       e);

	/* key size: 16 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector16_key,
		       sizeof(hmac_sha224_vector16_key),
		       hmac_sha224_vector16_in,
		       sizeof(hmac_sha224_vector16_in),
		       hmac_sha224_vector16_out,
		       sizeof(hmac_sha224_vector16_out),
		       e);

	/* key size: 20 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector20_key,
		       sizeof(hmac_sha224_vector20_key),
		       hmac_sha224_vector20_in,
		       sizeof(hmac_sha224_vector20_in),
		       hmac_sha224_vector20_out,
		       sizeof(hmac_sha224_vector20_out),
		       e);

	/* key size: 24 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector24_key,
		       sizeof(hmac_sha224_vector24_key),
		       hmac_sha224_vector24_in,
		       sizeof(hmac_sha224_vector24_in),
		       hmac_sha224_vector24_out,
		       sizeof(hmac_sha224_vector24_out),
		       e);

	/* key size: 28 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector28_key,
		       sizeof(hmac_sha224_vector28_key),
		       hmac_sha224_vector28_in,
		       sizeof(hmac_sha224_vector28_in),
		       hmac_sha224_vector28_out,
		       sizeof(hmac_sha224_vector28_out),
		       e);

	/* key size: 32 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector32_key,
		       sizeof(hmac_sha224_vector32_key),
		       hmac_sha224_vector32_in,
		       sizeof(hmac_sha224_vector32_in),
		       hmac_sha224_vector32_out,
		       sizeof(hmac_sha224_vector32_out),
		       e);

	/* key size: 48 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector48_key,
		       sizeof(hmac_sha224_vector48_key),
		       hmac_sha224_vector48_in,
		       sizeof(hmac_sha224_vector48_in),
		       hmac_sha224_vector48_out,
		       sizeof(hmac_sha224_vector48_out),
		       e);

	/* key size: 64 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector64_key,
		       sizeof(hmac_sha224_vector64_key),
		       hmac_sha224_vector64_in,
		       sizeof(hmac_sha224_vector64_in),
		       hmac_sha224_vector64_out,
		       sizeof(hmac_sha224_vector64_out),
		       e);

	/* key size: 128 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector128_key,
		       sizeof(hmac_sha224_vector128_key),
		       hmac_sha224_vector128_in,
		       sizeof(hmac_sha224_vector128_in),
		       hmac_sha224_vector128_out,
		       sizeof(hmac_sha224_vector128_out),
		       e);

	/* key size: 256 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector256_key,
		       sizeof(hmac_sha224_vector256_key),
		       hmac_sha224_vector256_in,
		       sizeof(hmac_sha224_vector256_in),
		       hmac_sha224_vector256_out,
		       sizeof(hmac_sha224_vector256_out),
		       e);

	/* key size: 512 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector512_key,
		       sizeof(hmac_sha224_vector512_key),
		       hmac_sha224_vector512_in,
		       sizeof(hmac_sha224_vector512_in),
		       hmac_sha224_vector512_out,
		       sizeof(hmac_sha224_vector512_out),
		       e);

	/* key size: 1024 bytes */
	count += test_hmac_vector(md,
		       hmac_sha224_vector1024_key,
		       sizeof(hmac_sha224_vector1024_key),
		       hmac_sha224_vector1024_in,
		       sizeof(hmac_sha224_vector1024_in),
		       hmac_sha224_vector1024_out,
		       sizeof(hmac_sha224_vector1024_out),
		       e);

	/* multiblock test */
	count += test_hmac_vector(md,
		       hmac_vector1024_multiblock_key,
		       sizeof(hmac_vector1024_multiblock_key),
		       hmac_vector1024_multiblock_in,
		       sizeof(hmac_vector1024_multiblock_in),
		       hmac_sha224_vector1024_multiblock_out,
		       sizeof(hmac_sha224_vector1024_multiblock_out),
		       e);

	/* SHA-256 */
sha2_256:

	if (algo != 32)
		goto sha2_384;

	md = algo;

	/* key size: 14 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector14_key,
		       sizeof(hmac_sha256_vector14_key),
		       hmac_sha256_vector14_in,
		       sizeof(hmac_sha256_vector14_in),
		       hmac_sha256_vector14_out,
		       sizeof(hmac_sha256_vector14_out),
		       e);

	/* key size: 16 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector16_key,
		       sizeof(hmac_sha256_vector16_key),
		       hmac_sha256_vector16_in,
		       sizeof(hmac_sha256_vector16_in),
		       hmac_sha256_vector16_out,
		       sizeof(hmac_sha256_vector16_out),
		       e);

	/* key size: 20 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector20_key,
		       sizeof(hmac_sha256_vector20_key),
		       hmac_sha256_vector20_in,
		       sizeof(hmac_sha256_vector20_in),
		       hmac_sha256_vector20_out,
		       sizeof(hmac_sha256_vector20_out),
		       e);

	/* key size: 24 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector24_key,
		       sizeof(hmac_sha256_vector24_key),
		       hmac_sha256_vector24_in,
		       sizeof(hmac_sha256_vector24_in),
		       hmac_sha256_vector24_out,
		       sizeof(hmac_sha256_vector24_out),
		       e);

	/* key size: 28 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector28_key,
		       sizeof(hmac_sha256_vector28_key),
		       hmac_sha256_vector28_in,
		       sizeof(hmac_sha256_vector28_in),
		       hmac_sha256_vector28_out,
		       sizeof(hmac_sha256_vector28_out),
		       e);


	/* key size: 32 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector32_key,
		       sizeof(hmac_sha256_vector32_key),
		       hmac_sha256_vector32_in,
		       sizeof(hmac_sha256_vector32_in),
		       hmac_sha256_vector32_out,
		       sizeof(hmac_sha256_vector32_out),
		       e);

	/* key size: 48 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector48_key,
		       sizeof(hmac_sha256_vector48_key),
		       hmac_sha256_vector48_in,
		       sizeof(hmac_sha256_vector48_in),
		       hmac_sha256_vector48_out,
		       sizeof(hmac_sha256_vector48_out),
		       e);

	/* key size: 64 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector64_key,
		       sizeof(hmac_sha256_vector64_key),
		       hmac_sha256_vector64_in,
		       sizeof(hmac_sha256_vector64_in),
		       hmac_sha256_vector64_out,
		       sizeof(hmac_sha256_vector64_out),
		       e);

	/* key size: 128 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector128_key,
		       sizeof(hmac_sha256_vector128_key),
		       hmac_sha256_vector128_in,
		       sizeof(hmac_sha256_vector128_in),
		       hmac_sha256_vector128_out,
		       sizeof(hmac_sha256_vector128_out),
		       e);

	/* key size: 256 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector256_key,
		       sizeof(hmac_sha256_vector256_key),
		       hmac_sha256_vector256_in,
		       sizeof(hmac_sha256_vector256_in),
		       hmac_sha256_vector256_out,
		       sizeof(hmac_sha256_vector256_out),
		       e);

	/* key size: 512 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector512_key,
		       sizeof(hmac_sha256_vector512_key),
		       hmac_sha256_vector512_in,
		       sizeof(hmac_sha256_vector512_in),
		       hmac_sha256_vector512_out,
		       sizeof(hmac_sha256_vector512_out),
		       e);

	/* key size: 1024 bytes */
	count += test_hmac_vector(md,
		       hmac_sha256_vector1024_key,
		       sizeof(hmac_sha256_vector1024_key),
		       hmac_sha256_vector1024_in,
		       sizeof(hmac_sha256_vector1024_in),
		       hmac_sha256_vector1024_out,
		       sizeof(hmac_sha256_vector1024_out),
		       e);

	/* multiblock test */
	count += test_hmac_vector(md,
		       hmac_vector1024_multiblock_key,
		       sizeof(hmac_vector1024_multiblock_key),
		       hmac_vector1024_multiblock_in,
		       sizeof(hmac_vector1024_multiblock_in),
		       hmac_sha256_vector1024_multiblock_out,
		       sizeof(hmac_sha256_vector1024_multiblock_out),
		       e);

	/* SHA-384 */
sha2_384:

	if (algo != 48)
		goto sha2_512;

	md = algo;

	/* key size: 14 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector14_key,
		       sizeof(hmac_sha384_vector14_key),
		       hmac_sha384_vector14_in,
		       sizeof(hmac_sha384_vector14_in),
		       hmac_sha384_vector14_out,
		       sizeof(hmac_sha384_vector14_out),
		       e);

	/* key size: 16 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector16_key,
		       sizeof(hmac_sha384_vector16_key),
		       hmac_sha384_vector16_in,
		       sizeof(hmac_sha384_vector16_in),
		       hmac_sha384_vector16_out,
		       sizeof(hmac_sha384_vector16_out),
		       e);

	/* key size: 20 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector20_key,
		       sizeof(hmac_sha384_vector20_key),
		       hmac_sha384_vector20_in,
		       sizeof(hmac_sha384_vector20_in),
		       hmac_sha384_vector20_out,
		       sizeof(hmac_sha384_vector20_out),
		       e);

	/* key size: 24 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector24_key,
		       sizeof(hmac_sha384_vector24_key),
		       hmac_sha384_vector24_in,
		       sizeof(hmac_sha384_vector24_in),
		       hmac_sha384_vector24_out,
		       sizeof(hmac_sha384_vector24_out),
		       e);

	/* key size: 28 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector28_key,
		       sizeof(hmac_sha384_vector28_key),
		       hmac_sha384_vector28_in,
		       sizeof(hmac_sha384_vector28_in),
		       hmac_sha384_vector28_out,
		       sizeof(hmac_sha384_vector28_out),
		       e);

	/* key size: 32 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector32_key,
		       sizeof(hmac_sha384_vector32_key),
		       hmac_sha384_vector32_in,
		       sizeof(hmac_sha384_vector32_in),
		       hmac_sha384_vector32_out,
		       sizeof(hmac_sha384_vector32_out),
		       e);

	/* key size: 48 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector48_key,
		       sizeof(hmac_sha384_vector48_key),
		       hmac_sha384_vector48_in,
		       sizeof(hmac_sha384_vector48_in),
		       hmac_sha384_vector48_out,
		       sizeof(hmac_sha384_vector48_out),
		       e);

	/* key size: 64 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector64_key,
		       sizeof(hmac_sha384_vector64_key),
		       hmac_sha384_vector64_in,
		       sizeof(hmac_sha384_vector64_in),
		       hmac_sha384_vector64_out,
		       sizeof(hmac_sha384_vector64_out),
		       e);

	/* key size: 128 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector128_key,
		       sizeof(hmac_sha384_vector128_key),
		       hmac_sha384_vector128_in,
		       sizeof(hmac_sha384_vector128_in),
		       hmac_sha384_vector128_out,
		       sizeof(hmac_sha384_vector128_out),
		       e);

	/* key size: 256 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector256_key,
		       sizeof(hmac_sha384_vector256_key),
		       hmac_sha384_vector256_in,
		       sizeof(hmac_sha384_vector256_in),
		       hmac_sha384_vector256_out,
		       sizeof(hmac_sha384_vector256_out),
		       e);

	/* key size: 512 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector512_key,
		       sizeof(hmac_sha384_vector512_key),
		       hmac_sha384_vector512_in,
		       sizeof(hmac_sha384_vector512_in),
		       hmac_sha384_vector512_out,
		       sizeof(hmac_sha384_vector512_out),
		       e);

	/* key size: 1024 bytes */
	count += test_hmac_vector(md,
		       hmac_sha384_vector1024_key,
		       sizeof(hmac_sha384_vector1024_key),
		       hmac_sha384_vector1024_in,
		       sizeof(hmac_sha384_vector1024_in),
		       hmac_sha384_vector1024_out,
		       sizeof(hmac_sha384_vector1024_out),
		       e);

	/* multiblock test */
	count += test_hmac_vector(md,
		       hmac_vector1024_multiblock_key,
		       sizeof(hmac_vector1024_multiblock_key),
		       hmac_vector1024_multiblock_in,
		       sizeof(hmac_vector1024_multiblock_in),
		       hmac_sha384_vector1024_multiblock_out,
		       sizeof(hmac_sha384_vector1024_multiblock_out),
		       e);

	/* SHA-512 */
sha2_512:

	if (algo != 64)
		goto sha_finish;

	md = algo;

	/* key size: 14 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector14_key,
		       sizeof(hmac_sha512_vector14_key),
		       hmac_sha512_vector14_in,
		       sizeof(hmac_sha512_vector14_in),
		       hmac_sha512_vector14_out,
		       sizeof(hmac_sha512_vector14_out),
		       e);

	/* key size: 16 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector16_key,
		       sizeof(hmac_sha512_vector16_key),
		       hmac_sha512_vector16_in,
		       sizeof(hmac_sha512_vector16_in),
		       hmac_sha512_vector16_out,
		       sizeof(hmac_sha512_vector16_out),
		       e);

	/* key size: 20 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector20_key,
		       sizeof(hmac_sha512_vector20_key),
		       hmac_sha512_vector20_in,
		       sizeof(hmac_sha512_vector20_in),
		       hmac_sha512_vector20_out,
		       sizeof(hmac_sha512_vector20_out),
		       e);

	/* key size: 24 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector24_key,
		       sizeof(hmac_sha512_vector24_key),
		       hmac_sha512_vector24_in,
		       sizeof(hmac_sha512_vector24_in),
		       hmac_sha512_vector24_out,
		       sizeof(hmac_sha512_vector24_out),
		       e);

	/* key size: 28 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector28_key,
		       sizeof(hmac_sha512_vector28_key),
		       hmac_sha512_vector28_in,
		       sizeof(hmac_sha512_vector28_in),
		       hmac_sha512_vector28_out,
		       sizeof(hmac_sha512_vector28_out),
		       e);

	/* key size: 32 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector32_key,
		       sizeof(hmac_sha512_vector32_key),
		       hmac_sha512_vector32_in,
		       sizeof(hmac_sha512_vector32_in),
		       hmac_sha512_vector32_out,
		       sizeof(hmac_sha512_vector32_out),
		       e);

	/* key size: 48 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector48_key,
		       sizeof(hmac_sha512_vector48_key),
		       hmac_sha512_vector48_in,
		       sizeof(hmac_sha512_vector48_in),
		       hmac_sha512_vector48_out,
		       sizeof(hmac_sha512_vector48_out),
		       e);

	/* key size: 64 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector64_key,
		       sizeof(hmac_sha512_vector64_key),
		       hmac_sha512_vector64_in,
		       sizeof(hmac_sha512_vector64_in),
		       hmac_sha512_vector64_out,
		       sizeof(hmac_sha512_vector64_out),
		       e);

	/* key size: 128 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector128_key,
		       sizeof(hmac_sha512_vector128_key),
		       hmac_sha512_vector128_in,
		       sizeof(hmac_sha512_vector128_in),
		       hmac_sha512_vector128_out,
		       sizeof(hmac_sha512_vector128_out),
		       e);

	/* key size: 256 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector256_key,
		       sizeof(hmac_sha512_vector256_key),
		       hmac_sha512_vector256_in,
		       sizeof(hmac_sha512_vector256_in),
		       hmac_sha512_vector256_out,
		       sizeof(hmac_sha512_vector256_out),
		       e);

	/* key size: 512 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector512_key,
		       sizeof(hmac_sha512_vector512_key),
		       hmac_sha512_vector512_in,
		       sizeof(hmac_sha512_vector512_in),
		       hmac_sha512_vector512_out,
		       sizeof(hmac_sha512_vector512_out),
		       e);

	/* key size: 1024 bytes */
	count += test_hmac_vector(md,
		       hmac_sha512_vector1024_key,
		       sizeof(hmac_sha512_vector1024_key),
		       hmac_sha512_vector1024_in,
		       sizeof(hmac_sha512_vector1024_in),
		       hmac_sha512_vector1024_out,
		       sizeof(hmac_sha512_vector1024_out),
		       e);

	/* multiblock test */
	count += test_hmac_vector(md,
		       hmac_vector1024_multiblock_key,
		       sizeof(hmac_vector1024_multiblock_key),
		       hmac_vector1024_multiblock_in,
		       sizeof(hmac_vector1024_multiblock_in),
		       hmac_sha512_vector1024_multiblock_out,
		       sizeof(hmac_sha512_vector1024_multiblock_out),
		       e);

sha_finish:
	if (count != test_hmac_vector_num_calls) {
		res = PS_FAILURE;
		_psTrace("FAILED: some of the tests failed.\n");
	} else {
		_psTraceInt("PASSED (%d vectors)\n", count);
	}
	test_hmac_vector_num_calls = 0;
	return res;
}

static int32 psHmacVectorTestsSHA1(void)
{
	return psHmacVectorTestsShared(20);
}

static int32 psHmacVectorTestsSHA256(void)
{
	return psHmacVectorTestsShared(32);
}

static int32 psHmacVectorTestsSHA384(void)
{
	return psHmacVectorTestsShared(48);
}


static int32 psHmacVectorTestsSimultaneous(void)
{
	psHmacSha1_t ctx1;
	psHmacSha1_t ctx2;
	psHmacSha1_t ctx3;
	int32 rv1;
	int32 rv2;
	int32 rv3;
	unsigned char md1[20];
	unsigned char md2[20];
	unsigned char md3[20];

	rv1 = psHmacSha1Init(&ctx1, (unsigned char *) hmac_sha1_vector14_key,
						 sizeof(hmac_sha1_vector14_key));
	rv2 = psHmacSha1Init(&ctx2, (unsigned char *) hmac_sha1_vector16_key,
						 sizeof(hmac_sha1_vector16_key));
	rv3 = psHmacSha1Init(&ctx3, (unsigned char *) hmac_sha1_vector20_key,
				   sizeof(hmac_sha1_vector20_key));

	if (rv1 != PS_SUCCESS) {
		_psTrace("FAILED (hmac_sha1_vector14)\n");
	}
	if (rv2 != PS_SUCCESS) {
		_psTrace("FAILED (hmac_sha1_vector16)\n");
	}
	if (rv3 != PS_SUCCESS) {
		_psTrace("FAILED (hmac_sha1_vector20)\n");
	}

	psHmacSha1Update(&ctx1, hmac_sha1_vector14_in,
					 sizeof(hmac_sha1_vector14_in));
	psHmacSha1Update(&ctx2, hmac_sha1_vector16_in,
					 sizeof(hmac_sha1_vector16_in));
	psHmacSha1Update(&ctx3, hmac_sha1_vector20_in,
					 sizeof(hmac_sha1_vector20_in));

	psHmacSha1Final(&ctx1, md1);
	psHmacSha1Final(&ctx2, md2);
	psHmacSha1Final(&ctx3, md3);

	if (memcmp(md1, hmac_sha1_vector14_out,
			   sizeof(hmac_sha1_vector14_out)) != 0) {
		_psTrace("FAILED (hmac_sha1_vector14)\n");
		return PS_FAILURE;
	}
	if (memcmp(md2, hmac_sha1_vector16_out,
			   sizeof(hmac_sha1_vector16_out)) != 0) {
		_psTrace("FAILED (hmac_sha1_vector16)\n");
		return PS_FAILURE;
	}
	if (memcmp(md3, hmac_sha1_vector20_out,
			   sizeof(hmac_sha1_vector20_out)) != 0) {
		_psTrace("FAILED (hmac_sha1_vector20)\n");
		return PS_FAILURE;
	}

	_psTrace("PASSED\n");
	return PS_SUCCESS;
}


static int32 psHmacVectorTests(void)
{
	int32 res;

	res = psHmacVectorTestSimple();

	_psTraceInt("	SHA-1 known vector test %d... ", 2);
	res |= psHmacVectorTestsSHA1();

	_psTraceInt("	SHA-256 known vector test %d... ", 1);
	res |= psHmacVectorTestsSHA256();

	_psTraceInt("	SHA-384 known vector test %d... ", 1);
	res |= psHmacVectorTestsSHA384();

	_psTrace("	Simultaneous hmac contexts... ");
	res |= psHmacVectorTestsSimultaneous();

	return res;
}

#endif /* USE_HMAC */


/******************************************************************************/

#ifdef USE_ECC

#include "../../testkeys/EC/256_EC.h"
#include "../../testkeys/EC/256_EC_KEY.h"

static int32_t ecdh_kat(unsigned char *alice_priv,
						size_t alice_priv_len,
						unsigned char *bob_pub,
						size_t bob_pub_len,
						unsigned char *expected_secret,
						size_t expected_secret_len,
					    int curve_id)
{
	psPool_t			*pool = NULL;
	psEccKey_t			privkey = PS_ECC_STATIC_INIT;
	psEccKey_t			pubkey_imported = PS_ECC_STATIC_INIT;
	const psEccCurve_t	*curve;
	unsigned char got_secret[128] = {0};
	int32_t rc;
	uint16_t secret_len;

	if (getEccParamById(curve_id, &curve) < 0) {
	    return PS_FAIL;
	}

	rc = psEccParsePrivKey(pool, alice_priv, alice_priv_len,
						   &privkey, curve);

	if (rc != PS_SUCCESS) {
		_psTrace("psEccParsePrivKey failed\n");
		rc = PS_FAIL;
		goto L_FAIL;
	}

	rc = psEccX963ImportKey(pool, bob_pub, bob_pub_len,
							&pubkey_imported, curve);

	if (rc != PS_SUCCESS) {
		_psTrace("psEccX963ImportKey failed\n");
		rc = PS_FAIL;
		goto L_FAIL;
	}

	secret_len = sizeof(got_secret);
	rc = psEccGenSharedSecret(pool, &privkey, &pubkey_imported,
							  got_secret, &secret_len, NULL);

	if (rc != PS_SUCCESS) {
		_psTrace("psEccGenSharedSecret failed\n");
		rc = PS_FAIL;
		goto L_FAIL;
	}

	if (secret_len != expected_secret_len) {
		_psTrace("Unexpected shared secret size\n");
		rc = PS_FAIL;
		goto L_FAIL;
	}

	if (memcmp(got_secret, expected_secret, secret_len)) {
		_psTrace("KAT failed\n");
		rc = PS_FAIL;
		goto L_FAIL;
	}

	rc = PS_SUCCESS;
	_psTrace(" PASSED\n");


L_FAIL:
	psEccClearKey(&privkey);
	psEccClearKey(&pubkey_imported);

	return rc;
}

static int32_t ecdh_p256_kat(void)
{
	int32_t rc;

/* A prime256v1 keypair and an ECDH shared secret generated with it. */
	unsigned char alice_priv[] =
	{
		0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x2a, 0x50, 0x32, 0x9a, 0xa5,
		0x7e, 0x0d, 0xc0, 0x1f, 0xf9, 0xb1, 0xeb, 0xe4, 0x01, 0x4c, 0xc2, 0x87,
		0x78, 0x91, 0xe3, 0xb6, 0x53, 0x59, 0x77, 0x3c, 0x0e, 0x3c, 0x15, 0xa3,
		0xb5, 0x82, 0x96, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
		0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x42, 0x37, 0x6d,
		0xf6, 0x3e, 0x06, 0x70, 0x7f, 0xa2, 0x36, 0x8d, 0x37, 0x90, 0x92, 0x93,
		0xe5, 0xc3, 0x70, 0x94, 0x00, 0xd1, 0x09, 0xb2, 0xb5, 0x70, 0xa1, 0x82,
		0xfe, 0xa6, 0xb0, 0xfc, 0xfa, 0x18, 0xea, 0x5e, 0xff, 0x87, 0x0f, 0xbf,
		0xd5, 0xd6, 0x8b, 0x88, 0xb9, 0x1a, 0xcf, 0xf9, 0x53, 0xd2, 0xb0, 0x5c,
		0x7b, 0x2f, 0x71, 0xf5, 0x95, 0xb0, 0xa1, 0x3d, 0xd6, 0xa5, 0x59, 0x14,
		0x56
	};
	unsigned char bob_pub[] =
	{
		0x04, 0x32, 0xee, 0xb1, 0x56, 0xf9, 0xb1, 0xc9, 0x80, 0x66, 0xa5, 0x7d,
		0x94, 0xff, 0xde, 0x61, 0xbd, 0x3f, 0x2d, 0xf0, 0x1f, 0xc0, 0xb5, 0x1e,
		0xc1, 0x05, 0x5b, 0x2b, 0xf9, 0x2a, 0x39, 0x6a, 0x94, 0x82, 0x6b, 0x77,
		0xd4, 0xb9, 0x07, 0x02, 0xdb, 0x73, 0x6f, 0x95, 0xe9, 0xc3, 0xbd, 0xd5,
		0x25, 0x5f, 0xea, 0x0b, 0xc4, 0xa6, 0x60, 0x83, 0x5c, 0xe4, 0x3a, 0xd9,
		0x08, 0xf9, 0x9b, 0x09, 0x8c
	};
	unsigned char secret[] =
	{
		0xb1, 0xe2, 0x6c, 0x88, 0xe7, 0x06, 0x12, 0x1e, 0x92, 0x0f, 0xc2, 0x89,
		0x35, 0x8d, 0x37, 0x36, 0x20, 0xfa, 0x81, 0x91, 0x53, 0x5d, 0x4c, 0xa1,
		0x71, 0x1f, 0x8c, 0x90, 0xa4, 0x7f, 0x8b, 0xf4
	};

	_psTrace("	P-256 ECDH known-answer test...");
    rc = ecdh_kat(alice_priv, sizeof(alice_priv),
				  bob_pub, sizeof(bob_pub),
				  secret, sizeof(secret),
				  IANA_SECP256R1);
	if (rc == PS_FAIL)
		_psTrace("P-256 ECDH known-answer test failed\n");
	return rc;
}

static int32_t ecdh_p384_kat(void)
{
	int32_t rc;
/* A secp384r1 keypair and an ECDH shared secret generated with it. */
	unsigned char alice_priv[] =
	{
		0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0xfc, 0x80, 0x44, 0xc5,
		0x86, 0xd4, 0x6a, 0x93, 0xa5, 0xd1, 0x33, 0xe0, 0x59, 0xe2, 0x5c, 0xca,
		0x04, 0x89, 0xc6, 0x0e, 0x45, 0xcb, 0x5a, 0x3b, 0x22, 0x07, 0x6d, 0xcc,
		0x1b, 0x49, 0xba, 0x80, 0xe9, 0x7f, 0x48, 0xb7, 0x7c, 0x9f, 0x49, 0x17,
		0xa0, 0x41, 0x81, 0x5e, 0xc0, 0x75, 0x2a, 0x9b, 0xa0, 0x07, 0x06, 0x05,
		0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0x6c,
		0xc2, 0x05, 0x72, 0x70, 0x4b, 0x07, 0x2f, 0x36, 0x7c, 0x77, 0xa3, 0x04,
		0xbe, 0x18, 0x56, 0x3f, 0xc9, 0xfa, 0x50, 0xe9, 0x2e, 0x0a, 0x24, 0x74,
		0xa1, 0x0d, 0x48, 0x92, 0x71, 0x62, 0xb4, 0xd5, 0x69, 0xad, 0x8c, 0x31,
		0xf0, 0xfe, 0xa5, 0x00, 0x6c, 0x1e, 0x34, 0x58, 0x1a, 0xd3, 0x83, 0x5a,
		0x79, 0x81, 0xc9, 0xb5, 0x2b, 0x0f, 0x72, 0x6b, 0x5d, 0x20, 0x7b, 0xba,
		0xd3, 0x4c, 0x93, 0xbb, 0xe4, 0x58, 0x46, 0x06, 0x92, 0xab, 0x5d, 0x30,
		0xff, 0x03, 0xf6, 0xfe, 0x1c, 0x87, 0xfb, 0x5a, 0x00, 0xa5, 0x7e, 0x5e,
		0xbd, 0x53, 0x02, 0x38, 0xe7, 0xf8, 0x53, 0x58, 0x19, 0x77, 0x2c
	};
	unsigned char bob_pub[] =
	{
		0x04, 0xba, 0x84, 0x0b, 0xd0, 0xab, 0xfd, 0x2f, 0x4c, 0x49, 0x19, 0x8c,
		0xbf, 0x97, 0x55, 0x2d, 0xbc, 0x2d, 0x2a, 0xf0, 0x8b, 0x8f, 0xfc, 0x2b,
		0x85, 0xdb, 0x02, 0x83, 0x9b, 0x41, 0xdd, 0x91, 0xda, 0xad, 0x1e, 0x43,
		0x81, 0x18, 0xc9, 0xf7, 0xc2, 0x5a, 0x06, 0x05, 0xc5, 0x9b, 0x72, 0xf8,
		0x5c, 0xf7, 0x25, 0xb3, 0x50, 0x98, 0x5e, 0x31, 0xa0, 0x24, 0x0f, 0xc4,
		0x9a, 0x2f, 0xc9, 0x6d, 0x4e, 0x2a, 0xab, 0xdb, 0x9e, 0xa1, 0x73, 0x36,
		0x5b, 0x3f, 0x39, 0xcf, 0x5f, 0x45, 0x0f, 0xa5, 0xc8, 0xfc, 0x40, 0x57,
		0xaf, 0x96, 0x0d, 0x25, 0xd6, 0x7e, 0x0b, 0xe1, 0x6a, 0x4d, 0x09, 0x08,
		0xca
	};
	unsigned char secret[] =
	{
		0x1b, 0x74, 0x01, 0x47, 0x86, 0x9a, 0x79, 0x25, 0x43, 0x2a, 0x39, 0x3f,
		0xe5, 0x8c, 0x7c, 0xb6, 0x9b, 0xd3, 0x19, 0xb0, 0x3d, 0xc2, 0xa2, 0xb0,
		0x6a, 0xca, 0x33, 0x66, 0x82, 0xb2, 0x47, 0x84, 0x1e, 0xe8, 0x71, 0xeb,
		0x68, 0x88, 0xfa, 0xfd, 0x08, 0x52, 0xe3, 0x2e, 0x04, 0x59, 0xe7, 0xe7
	};

	_psTrace("	P-384 ECDH known-answer test...");

    rc = ecdh_kat(alice_priv, sizeof(alice_priv),
				  bob_pub, sizeof(bob_pub),
				  secret, sizeof(secret),
				  IANA_SECP384R1);
	if (rc == PS_FAIL) {
		_psTrace("P-384 ECDH known-answer test failed\n");
		return rc;
	}

	return PS_SUCCESS;
}

#ifdef USE_SECP521R1
static int32_t ecdh_p521_kat(void)
{
	int32_t rc;
/* A secp521r1 keypair and an ECDH shared secret generated with it. */
	unsigned char alice_priv[] =
	{
		0x30, 0x81, 0xdc, 0x02, 0x01, 0x01, 0x04, 0x42, 0x00, 0x0e, 0x21, 0x99,
		0x99, 0x28, 0xe5, 0x42, 0x2f, 0x6b, 0xbc, 0x7a, 0xb5, 0x50, 0xe4, 0x6a,
		0xbd, 0xdc, 0x5e, 0x90, 0xb0, 0x5c, 0xd3, 0x19, 0x9b, 0xee, 0xc4, 0xab,
		0x66, 0x5a, 0x02, 0xba, 0x65, 0xce, 0xf6, 0xb1, 0x32, 0xa9, 0xca, 0x1c,
		0x42, 0x02, 0x99, 0xda, 0xf7, 0xae, 0x3c, 0x12, 0x14, 0x59, 0x73, 0xf1,
		0x28, 0xef, 0x17, 0xd4, 0xc5, 0xd9, 0xa9, 0xec, 0x77, 0x74, 0x3c, 0x0a,
		0x3a, 0x46, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0xa1,
		0x81, 0x89, 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x1a, 0x21, 0x9b, 0x8c,
		0x59, 0x86, 0x25, 0x5f, 0xb3, 0x52, 0xd3, 0xa6, 0xaf, 0x06, 0x06, 0x1e,
		0x3c, 0x89, 0x0d, 0x5d, 0xf4, 0xb9, 0x92, 0xd5, 0x1b, 0xe4, 0xa5, 0x20,
		0x9d, 0xd6, 0x3d, 0x01, 0x80, 0xee, 0x4b, 0xd4, 0xea, 0x0a, 0xe6, 0xd3,
		0x4e, 0xfa, 0xe9, 0x7f, 0xf9, 0xf9, 0x94, 0x65, 0x0e, 0x85, 0x54, 0xdd,
		0xc7, 0xfe, 0xae, 0x97, 0xd1, 0x6a, 0xd3, 0x7b, 0x90, 0x1f, 0x50, 0xcc,
		0x6a, 0x01, 0x88, 0x18, 0x09, 0x27, 0x83, 0x70, 0x28, 0xe4, 0x05, 0x88,
		0x03, 0xe9, 0x1b, 0x0b, 0x93, 0x5a, 0x3b, 0xba, 0x2d, 0x91, 0xff, 0x20,
		0x6f, 0xb4, 0x86, 0x91, 0x30, 0xdb, 0xf0, 0xa3, 0x08, 0xb0, 0x23, 0x61,
		0xa8, 0x80, 0x91, 0x53, 0x64, 0x93, 0x9a, 0x3c, 0xca, 0x50, 0x18, 0x04,
		0xb4, 0x9c, 0x78, 0xae, 0x48, 0xd6, 0x01, 0x51, 0x30, 0xd2, 0xcd, 0x7c,
		0x59, 0xdc, 0xfe, 0x20, 0x7c, 0xa7, 0x88
	};
	unsigned char bob_pub[] =
	{
		0x04, 0x01, 0xb4, 0xb3, 0x6a, 0x53, 0x35, 0x45, 0xbc, 0x72, 0xb7, 0x1c,
		0x34, 0x72, 0xb2, 0x24, 0x84, 0xb7, 0xe7, 0x1e, 0x67, 0x86, 0x8c, 0x2d,
		0xf8, 0x51, 0xb7, 0xe4, 0x06, 0xa5, 0x94, 0x8a, 0xfe, 0x27, 0xea, 0x82,
		0xd9, 0x14, 0x08, 0x73, 0xd7, 0xae, 0x16, 0xbf, 0x06, 0x4f, 0x3c, 0xf1,
		0x74, 0x60, 0x5e, 0x6e, 0xa2, 0xcc, 0x68, 0x67, 0xc0, 0x48, 0x50, 0xd2,
		0xfe, 0x24, 0x7d, 0xe4, 0x8e, 0x4b, 0xb6, 0x00, 0xce, 0x3a, 0xad, 0xdb,
		0x73, 0xb0, 0x39, 0x20, 0x6b, 0x19, 0x24, 0x33, 0x3f, 0x7a, 0xd8, 0xb5,
		0x59, 0x0a, 0x3a, 0x59, 0xc4, 0x49, 0xa3, 0x90, 0x6d, 0xc2, 0xa0, 0xf8,
		0x0d, 0xee, 0xd5, 0x00, 0x6b, 0x13, 0xb1, 0x08, 0x83, 0x7b, 0x3b, 0xda,
		0x16, 0x0f, 0x6b, 0x4c, 0x5e, 0xdb, 0xda, 0x94, 0xc7, 0x6c, 0xbc, 0xa3,
		0x2e, 0x13, 0xe2, 0xcf, 0x6a, 0xa2, 0x57, 0x46, 0x10, 0xd2, 0xab, 0x94,
		0x80
	};
	unsigned char secret[] =
	{
		0x00, 0x26, 0x96, 0xe5, 0x2b, 0xe4, 0x56, 0xac, 0x90, 0x0e, 0x5f, 0x9e,
		0x49, 0xf2, 0xd0, 0x19, 0x48, 0xa2, 0xf1, 0x2e, 0xe8, 0x1a, 0x47, 0x5c,
		0x30, 0xc7, 0x83, 0x59, 0xd4, 0x60, 0x55, 0x28, 0x95, 0x99, 0xa0, 0x65,
		0xc1, 0xeb, 0x8d, 0x92, 0x75, 0x63, 0x55, 0xa7, 0x4d, 0xe8, 0xb1, 0xe5,
		0x96, 0x50, 0x24, 0x45, 0x8f, 0x3d, 0xd2, 0x69, 0xb7, 0xca, 0xd3, 0x15,
		0x5a, 0xf6, 0x5c, 0x20, 0x5f, 0x49
	};

	_psTrace("	P-521 ECDH known-answer test...");

    rc = ecdh_kat(alice_priv, sizeof(alice_priv),
				  bob_pub, sizeof(bob_pub),
				  secret, sizeof(secret),
				  IANA_SECP521R1);
	if (rc == PS_FAIL) {
		_psTrace("P-521 ECDH known-answer test failed\n");
		return rc;
	}

	return PS_SUCCESS;
}
#endif /* USE_SECP521R1 */

static int32_t psEccPairwiseTest(void)
{
	psPool_t			*pool = NULL;
	psEccKey_t			k1 = PS_ECC_STATIC_INIT;
	psEccKey_t			k1_imported = PS_ECC_STATIC_INIT;
	psEccKey_t			k2 = PS_ECC_STATIC_INIT;
	psEccKey_t			k2_imported = PS_ECC_STATIC_INIT;
	psEccKey_t			priv = PS_ECC_STATIC_INIT;
	unsigned char k1_exported[256];
	unsigned char k2_exported[256];
	uint16_t k1len = sizeof(k1_exported);
	uint16_t k2len = sizeof(k2_exported);
	const psEccCurve_t	*curve;
	unsigned char		sk1k2[128], sk2k1[128];
	unsigned char		in[128], out[128];
	uint16_t			secretlen, inlen, outlen;
	int32_t				status, rc = PS_FAIL;
#ifdef USE_CERT_PARSE
	psX509Cert_t		*cert = NULL;
#endif /* USE_CERT_PARSE */

	if (getEccParamById(IANA_SECP256R1, &curve) < 0) {
		goto L_FAIL;
	}
	_psTraceStr("	%s Key Exchange...", curve->name);
	if (psEccGenKey(pool, &k1, curve, NULL) < 0) {
		goto L_FAIL;
	}
	if (psEccGenKey(pool, &k2, curve, NULL) < 0) {
		_psTrace("GenKey failed.");
		goto L_FAIL;
	}

	if (psEccX963ExportKey(pool, &k1, k1_exported, &k1len) < 0) {
		_psTrace("psEccX963ExportKey 1 failed.");
		goto L_FAIL;
	}
	if (psEccX963ExportKey(pool, &k2, k2_exported, &k2len) < 0) {
		_psTrace("psEccX963ExportKey 2 failed.");
		goto L_FAIL;
	}

	if (psEccX963ImportKey(pool, k1_exported, k1len, &k1_imported, curve) < 0) {
		_psTrace("psEccX963ImportKey 1 failed.");
		goto L_FAIL;
	}
	if (psEccX963ImportKey(pool, k2_exported, k2len, &k2_imported, curve) < 0) {
		_psTrace("psEccX963ImportKey 2 failed.");
		goto L_FAIL;
	}

	secretlen = sizeof(sk1k2);
	if (psEccGenSharedSecret(pool, &k1, &k2_imported, sk1k2, &secretlen, NULL) < 0 ||
			secretlen != curve->size) {
		_psTrace("GenSharedSecret K1 failed.");
		goto L_FAIL;
	}

	secretlen = sizeof(sk2k1);
	if (psEccGenSharedSecret(pool, &k2, &k1_imported, sk2k1, &secretlen, NULL) < 0 ||
			secretlen != curve->size) {
		_psTrace("GenSharedSecret K2 failed.");
		goto L_FAIL;
	}

	if (memcmpct(sk1k2, sk2k1, curve->size) != 0) {
		_psTrace("Shared secret doesn't match.");
		psTraceBytes("K1K2 Secret", sk1k2, secretlen);
		psTraceBytes("K2K1 Secret", sk2k1, secretlen);
		goto L_FAIL;
	}
	_psTrace(" PASSED\n");

	_psTraceStr("	%s Signature Validation...", curve->name);

	/* Generate some random bytes to sign */
	if (psGetEntropy(in, curve->size, NULL) < 0) {
		_psTrace("GetEntropy failed.");
		goto L_FAIL;
	}
	inlen = secretlen;

	/* Sign and verify with generated key 1*/
	outlen = sizeof(out);
	if (psEccDsaSign(pool, &k1, in, inlen, out, &outlen, 0, NULL) < 0) {
		_psTrace("Sign K1 failed.");
		goto L_FAIL;
	}

	if (psEccDsaVerify(pool, &k1_imported, in, inlen, out, outlen,
			&status, NULL) < 0 || status != 1) {
		_psTrace("K1 signature didn't validate.");
		goto L_FAIL;
	}

	/* Sign and verify with generated key 2, asking for a length prefix
	for TLS */
	outlen = sizeof(out);
	if (psEccDsaSign(pool, &k2, in, inlen, out, &outlen, 1, NULL) < 0) {
		_psTrace("Sign K2 failed.");
		goto L_FAIL;
	}

	/* Skip the first 2 bytes of length, as they are not the signature */
	if (psEccDsaVerify(pool, &k2_imported, in, inlen, out + 2, outlen - 2,
			&status, NULL) < 0 || status != 1) {
		_psTrace("K2 signature didn't validate.");
		goto L_FAIL;
	}

	/* Sign and verify with private key from header and corresponding public
		key in certificate, or with the private key if not parsing certs. */
	if (psEccParsePrivKey(pool, EC256KEY, sizeof(EC256KEY), &priv, curve) < 0) {
		_psTrace("ParsePrivKey failed.");
		goto L_FAIL;
	}
#ifdef USE_CERT_PARSE
	if (psX509ParseCert(pool, EC256, sizeof(EC256), &cert, 0) < 0) {
		_psTrace("ParseCert failed.");
		goto L_FAIL;
	}
#endif
	outlen = sizeof(out);
	if (psEccDsaSign(pool, &priv, in, inlen, out, &outlen, 1, NULL) < 0) {
		_psTrace("Sign header key failed.");
		goto L_FAIL;
	}
	if (psEccDsaVerify(pool,
#ifdef USE_CERT_PARSE
			&cert->publicKey.key.ecc,
#else
			&priv,
#endif
			in, inlen, out + 2, outlen - 2, &status, NULL) < 0 || status != 1) {
		_psTrace("Header key signature didn't validate.");
		goto L_FAIL;
	}

	rc = PS_SUCCESS;
	_psTrace(" PASSED\n");

L_FAIL:
	memzero_s(in, sizeof(in));
	memzero_s(out, sizeof(out));
	memzero_s(sk1k2, sizeof(sk1k2));
	memzero_s(sk2k1, sizeof(sk2k1));
	psEccClearKey(&k1);
	psEccClearKey(&k1_imported);
	psEccClearKey(&k2);
	psEccClearKey(&k2_imported);
	psEccClearKey(&priv);
#ifdef USE_CERT_PARSE
	if (cert) psX509FreeCert(cert);
#endif
	return rc;
}

static int32_t psEccTest(void)
{
	int32_t rc;

	rc = ecdh_p256_kat();
	if (rc != PS_SUCCESS)
		return rc;

	rc = ecdh_p384_kat();
	if (rc != PS_SUCCESS)
		return rc;

#ifdef USE_SECP521R1
	rc = ecdh_p521_kat();
	if (rc != PS_SUCCESS)
		return rc;
#endif /* USE_SECP521R1 */

	rc = psEccPairwiseTest();
	if (rc != PS_SUCCESS)
		return rc;

	return PS_SUCCESS;
}
#endif /* USE_ECC */

/******************************************************************************/

/******************************************************************************/

typedef struct {
	int32	(*fn)(void);
	char	name[64];
} test_t;

static test_t tests[] = {
#ifdef USE_AES
#ifdef USE_AES_BLOCK
{psAesTestBlock, "***** AES BLOCK TESTS *****"},
#endif
#ifdef USE_AES_CBC
{psAesTestCBC, "***** AES-CBC TESTS *****"},
#endif
#ifdef USE_AES_GCM
{psAesTestGCM, "***** AES-GCM TESTS *****"},
#endif
#else
{NULL, "AES"},
#endif

#ifdef USE_CHACHA20_POLY1305
{psChacha20Poly1305Test, "***** CHACHA20_POLY1305 TESTS *****"},
#endif

#ifdef USE_PKCS5
{psPBKDF2, "***** PBKDF2 TESTS *****"},
#endif

#ifdef USE_3DES
{psDes3Test
#else
{NULL
#endif
, "***** 3DES TESTS *****"},

#ifdef USE_SEED
{psSeedTest
#else
{NULL
#endif
, "***** SEED TESTS *****"},

#ifdef USE_ARC4
{psArc4Test
#else
{NULL
#endif
, "***** RC4 TESTS *****"},

#ifdef USE_IDEA
{psIdeaTest
#else
{NULL
#endif
, "***** IDEA TESTS *****"},

#ifdef USE_SHA1
{psSha1Test
#else
{NULL
#endif
, "***** SHA1 TESTS *****"},

#ifdef USE_SHA256
{psSha256Test
#else
{NULL
#endif
, "***** SHA256 TESTS *****"},

#ifdef USE_SHA384
{psSha384Test
#else
{NULL
#endif
, "***** SHA384 TESTS *****"},

#ifdef USE_SHA512
{psSha512Test
#else
{NULL
#endif
, "***** SHA512 TESTS *****"},

#ifdef USE_MD5
{psMd5Test
#else
{NULL
#endif
, "***** MD5 TESTS *****"},

#ifdef USE_MD5SHA1
{psMd5Sha1Test
#else
{NULL
#endif
, "***** MD5SHA1 TESTS *****"},

#ifdef USE_MD4
{psMd4Test
#else
{NULL
#endif
, "***** MD4 TESTS *****"},

#ifdef USE_MD2
{psMd2Test
#else
{NULL
#endif
, "***** MD2 TESTS *****"},

#ifdef USE_HMAC
{psHmacVectorTests
#else
{NULL
#endif
, "***** HMAC TESTS *****"},

{psPrngTests
, "***** PRNG TESTS *****"},

#ifdef USE_RSA
{psRsaEncryptTest
#else
{NULL
#endif
, "***** RSA ENCRYPT TESTS *****"},

#ifdef USE_RSA
{psRsaSignTest
#else
{NULL
#endif
, "***** RSA SIGN TESTS *****"},

#if defined(USE_PKCS1_OAEP) && !defined(USE_HARDWARE_CRYPTO_PKA)
{psRsaOaepVectorTest
#else
{NULL
#endif
, "***** RSA RSAES_OAEP TESTS *****"},

#if defined(USE_PKCS1_PSS) && !defined(USE_PKCS1_PSS_VERIFY_ONLY) && !defined(USE_HARDWARE_CRYPTO_PKA)
{psRsaPssVectorTest
#else
{NULL
#endif
, "***** RSA RSASSA_PSS TESTS *****"},

#ifdef USE_ECC
{psEccTest
#else
{NULL
#endif
, "***** ECC TESTS *****"},

{NULL
, "***** PRF TESTS *****"},

{NULL
, "***** PRF2 TESTS *****"},

{NULL, ""}
};

/******************************************************************************/
/*
	Main
*/

int main(int argc, char **argv)
{
	int32		i;

	if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) {
		_psTrace("Failed to initialize library:  psCryptoOpen failed\n");
		return -1;
	}

	for (i = 0; *tests[i].name; i++) {
		if (tests[i].fn) {
			_psTraceStr("%s\n", tests[i].name);
			tests[i].fn();
		} else {
			_psTraceStr("%s: SKIPPED\n", tests[i].name);
		}
	}
	printf("Finishing...\n");
	psCryptoClose();

#ifdef WIN32
	_psTrace("Press any key to close");
	getchar();
#endif

	return 0;
}
